From e9dc0db0e921db0c1f5f5e44876feaedcea44988 Mon Sep 17 00:00:00 2001 From: jigold Date: Wed, 28 Jun 2023 17:20:42 -0400 Subject: [PATCH 001/180] [batch] Add identifying metadata to Batch requests (#13219) I realize this looks like a lot of code changes, but it's mostly copying and pasting two SQL procedures and changing one line in each. This adds 4 bits of metadata to requests that then can be queried as extra metadata: - batch_id - job_id - batch_operation - job_queue_time Should be self-explanatory except job_queue time is the time in which the job is first set to ready to when it was scheduled on the worker (exact moment is when the job config is made to send to the worker). Example logging query. Note that the search on "batch_id" is not optimized so you definitely want to add some kind of time limit that's short on the window to search. I can add my Python script that scrapes these logs and makes a Plotly figure in a separate PR once this goes in. ``` ( resource.labels.container_name="batch" resource.labels.namespace_name="{namespace}" ) OR ( resource.labels.container_name="batch-driver" resource.labels.namespace_name="{namespace}" ) OR ( resource.type="gce_instance" logName:"worker.log" labels."compute.googleapis.com/resource_name":"{namespace}" ) jsonPayload.batch_id="{batch_id}" timestamp >= "{start_timestamp}" {end_timestamp} ``` --- .../driver/instance_collection/job_private.py | 3 +- .../batch/driver/instance_collection/pool.py | 6 +- batch/batch/driver/job.py | 1 + batch/batch/driver/main.py | 38 +++- batch/batch/front_end/front_end.py | 54 ++++- batch/batch/utils.py | 18 ++ batch/batch/worker/worker.py | 25 +- batch/sql/add-jobs-ready-time.sql | 213 ++++++++++++++++++ batch/sql/estimated-current.sql | 16 +- build.yaml | 3 + hail/python/hailtop/hail_logging.py | 15 +- 11 files changed, 358 insertions(+), 34 deletions(-) create mode 100644 batch/sql/add-jobs-ready-time.sql diff --git a/batch/batch/driver/instance_collection/job_private.py b/batch/batch/driver/instance_collection/job_private.py index 0641572c1d6..91c97860480 100644 --- a/batch/batch/driver/instance_collection/job_private.py +++ b/batch/batch/driver/instance_collection/job_private.py @@ -178,9 +178,10 @@ async def schedule_jobs_loop_body(self): async for record in self.db.select_and_fetchall( ''' -SELECT jobs.*, batches.format_version, batches.userdata, batches.user, attempts.instance_name +SELECT jobs.*, batches.format_version, batches.userdata, batches.user, attempts.instance_name, time_ready FROM batches INNER JOIN jobs ON batches.id = jobs.batch_id +LEFT JOIN jobs_telemetry ON jobs.batch_id = jobs_telemetry.batch_id AND jobs.job_id = jobs_telemetry.job_id LEFT JOIN attempts ON jobs.batch_id = attempts.batch_id AND jobs.job_id = attempts.job_id LEFT JOIN instances ON attempts.instance_name = instances.name WHERE batches.state = 'running' diff --git a/batch/batch/driver/instance_collection/pool.py b/batch/batch/driver/instance_collection/pool.py index 83052a68e1d..8bce99a71ec 100644 --- a/batch/batch/driver/instance_collection/pool.py +++ b/batch/batch/driver/instance_collection/pool.py @@ -618,8 +618,9 @@ async def user_runnable_jobs(user): ): async for record in self.db.select_and_fetchall( ''' -SELECT jobs.job_id, spec, cores_mcpu, regions_bits_rep +SELECT jobs.job_id, spec, cores_mcpu, regions_bits_rep, time_ready FROM jobs FORCE INDEX(jobs_batch_id_state_always_run_inst_coll_cancelled) +LEFT JOIN jobs_telemetry ON jobs.batch_id = jobs_telemetry.batch_id AND jobs.job_id = jobs_telemetry.job_id WHERE jobs.batch_id = %s AND inst_coll = %s AND jobs.state = 'Ready' AND always_run = 1 ORDER BY jobs.batch_id, inst_coll, state, always_run, -n_regions DESC, regions_bits_rep, jobs.job_id LIMIT 300; @@ -635,8 +636,9 @@ async def user_runnable_jobs(user): if not batch['cancelled']: async for record in self.db.select_and_fetchall( ''' -SELECT jobs.job_id, spec, cores_mcpu, regions_bits_rep +SELECT jobs.job_id, spec, cores_mcpu, regions_bits_rep, time_ready FROM jobs FORCE INDEX(jobs_batch_id_state_always_run_cancelled) +LEFT JOIN jobs_telemetry ON jobs.batch_id = jobs_telemetry.batch_id AND jobs.job_id = jobs_telemetry.job_id WHERE jobs.batch_id = %s AND inst_coll = %s AND jobs.state = 'Ready' AND always_run = 0 AND cancelled = 0 ORDER BY jobs.batch_id, inst_coll, state, always_run, -n_regions DESC, regions_bits_rep, jobs.job_id LIMIT 300; diff --git a/batch/batch/driver/job.py b/batch/batch/driver/job.py index 411a802f730..7d5f95988f9 100644 --- a/batch/batch/driver/job.py +++ b/batch/batch/driver/job.py @@ -434,6 +434,7 @@ async def job_config(app, record, attempt_id): 'user': record['user'], 'gsa_key': gsa_key, 'job_spec': job_spec, + 'queue_time': time_msecs() - record['time_ready'] if record['time_ready'] else None, } diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 6b83701f8eb..e65ddfa7953 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -56,6 +56,7 @@ from ..globals import HTTP_CLIENT_MAX_SIZE from ..inst_coll_config import InstanceCollectionConfigs, PoolConfig from ..utils import ( + add_metadata_to_request, authorization_token, batch_only, json_to_value, @@ -185,6 +186,7 @@ async def get_check_invariants(request, userdata): # pylint: disable=unused-arg @routes.patch('/api/v1alpha/batches/{user}/{batch_id}/update') @batch_only +@add_metadata_to_request async def update_batch(request): db = request.app['db'] @@ -269,6 +271,7 @@ async def get_credentials(request, instance): # pylint: disable=unused-argument @routes.post('/api/v1alpha/instances/activate') @activating_instances_only +@add_metadata_to_request async def activate_instance(request, instance): return await asyncio.shield(activate_instance_1(request, instance)) @@ -281,6 +284,7 @@ async def deactivate_instance_1(instance): @routes.post('/api/v1alpha/instances/deactivate') @active_instances_only +@add_metadata_to_request async def deactivate_instance(request, instance): # pylint: disable=unused-argument await asyncio.shield(deactivate_instance_1(instance)) return web.Response() @@ -319,6 +323,9 @@ async def job_complete_1(request, instance): job_id = job_status['job_id'] attempt_id = job_status['attempt_id'] + request['batch_telemetry']['batch_id'] = str(batch_id) + request['batch_telemetry']['job_id'] = str(job_id) + state = job_status['state'] if state == 'succeeded': new_state = 'Success' @@ -355,6 +362,7 @@ async def job_complete_1(request, instance): @routes.post('/api/v1alpha/instances/job_complete') @active_instances_only +@add_metadata_to_request async def job_complete(request, instance): return await asyncio.shield(job_complete_1(request, instance)) @@ -369,6 +377,9 @@ async def job_started_1(request, instance): start_time = job_status['start_time'] resources = job_status.get('resources') + request['batch_telemetry']['batch_id'] = str(batch_id) + request['batch_telemetry']['job_id'] = str(job_id) + await mark_job_started(request.app, batch_id, job_id, attempt_id, instance, start_time, resources) await instance.mark_healthy() @@ -378,6 +389,7 @@ async def job_started_1(request, instance): @routes.post('/api/v1alpha/instances/job_started') @active_instances_only +@add_metadata_to_request async def job_started(request, instance): return await asyncio.shield(job_started_1(request, instance)) @@ -415,6 +427,7 @@ async def billing_update_1(request, instance): @routes.post('/api/v1alpha/billing_update') @active_instances_only +@add_metadata_to_request async def billing_update(request, instance): return await asyncio.shield(billing_update_1(request, instance)) @@ -1349,18 +1362,21 @@ async def refresh_globals_from_db(app, db): class BatchDriverAccessLogger(AccessLogger): def __init__(self, logger: logging.Logger, log_format: str): super().__init__(logger, log_format) - self.exclude = [ - (endpoint[0], re.compile(deploy_config.base_path('batch-driver') + endpoint[1])) - for endpoint in [ - ('POST', '/api/v1alpha/instances/billing_update'), - ('POST', '/api/v1alpha/instances/job_complete'), - ('POST', '/api/v1alpha/instances/job_started'), - ('PATCH', '/api/v1alpha/batches/.*/.*/close'), - ('POST', '/api/v1alpha/batches/cancel'), - ('PATCH', '/api/v1alpha/batches/.*/.*/update'), - ('GET', '/metrics'), + if DEFAULT_NAMESPACE == 'default': + self.exclude = [ + (endpoint[0], re.compile(deploy_config.base_path('batch-driver') + endpoint[1])) + for endpoint in [ + ('POST', '/api/v1alpha/instances/billing_update'), + ('POST', '/api/v1alpha/instances/job_complete'), + ('POST', '/api/v1alpha/instances/job_started'), + ('PATCH', '/api/v1alpha/batches/.*/.*/close'), + ('POST', '/api/v1alpha/batches/cancel'), + ('PATCH', '/api/v1alpha/batches/.*/.*/update'), + ('GET', '/metrics'), + ] ] - ] + else: + self.exclude = [] def log(self, request, response, time): for method, path_expr in self.exclude: diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index 2d0e34bc2d8..e8972d258c3 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -82,6 +82,7 @@ from ..resource_usage import ResourceUsageMonitor from ..spec_writer import SpecWriter from ..utils import ( + add_metadata_to_request, query_billing_projects_with_cost, query_billing_projects_without_cost, regions_to_bits_rep, @@ -268,6 +269,7 @@ async def _get_jobs(request, batch_id: int, version: int, q: str, last_job_id: O @routes.get('/api/v1alpha/batches/{batch_id}/jobs') @rest_billing_project_users_only +@add_metadata_to_request async def get_jobs_v1(request, userdata, batch_id): # pylint: disable=unused-argument q = request.query.get('q', '') last_job_id = request.query.get('last_job_id') @@ -279,6 +281,7 @@ async def get_jobs_v1(request, userdata, batch_id): # pylint: disable=unused-ar @routes.get('/api/v2alpha/batches/{batch_id}/jobs') @rest_billing_project_users_only +@add_metadata_to_request async def get_jobs_v2(request, userdata, batch_id): # pylint: disable=unused-argument q = request.query.get('q', '') last_job_id = request.query.get('last_job_id') @@ -563,6 +566,7 @@ async def _get_full_job_status(app, record): # deprecated @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log') @rest_billing_project_users_only +@add_metadata_to_request async def get_job_log(request, userdata, batch_id): # pylint: disable=unused-argument job_id = int(request.match_info['job_id']) job_log_bytes = await _get_job_log(request.app, batch_id, job_id) @@ -591,6 +595,7 @@ async def get_job_container_log(request, batch_id): @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log/{container}') @rest_billing_project_users_only +@add_metadata_to_request async def rest_get_job_container_log(request, userdata, batch_id): # pylint: disable=unused-argument return await get_job_container_log(request, batch_id) @@ -728,6 +733,7 @@ async def _query_batches(request, user, q): @routes.get('/api/v1alpha/batches') @auth.rest_authenticated_users_only +@add_metadata_to_request async def get_batches(request, userdata): # pylint: disable=unused-argument user = userdata['username'] q = request.query.get('q', f'user:{user}') @@ -753,9 +759,9 @@ def check_service_account_permissions(user, sa): # Deprecated. Use create_jobs_for_update instead @routes.post('/api/v1alpha/batches/{batch_id}/jobs/create') @auth.rest_authenticated_users_only +@add_metadata_to_request async def create_jobs(request: aiohttp.web.Request, userdata: dict): app = request.app - batch_id = int(request.match_info['batch_id']) job_specs = await json_request(request) return await _create_jobs(userdata, job_specs, batch_id, 1, app) @@ -763,6 +769,7 @@ async def create_jobs(request: aiohttp.web.Request, userdata: dict): @routes.post('/api/v1alpha/batches/{batch_id}/updates/{update_id}/jobs/create') @auth.rest_authenticated_users_only +@add_metadata_to_request async def create_jobs_for_update(request: aiohttp.web.Request, userdata: dict): app = request.app @@ -824,6 +831,7 @@ async def _create_jobs(userdata: dict, job_specs: dict, batch_id: int, update_id jobs_args = [] job_parents_args = [] job_attributes_args = [] + jobs_telemetry_args = [] inst_coll_resources: Dict[str, Dict[str, int]] = collections.defaultdict( lambda: { @@ -1059,6 +1067,7 @@ async def _create_jobs(userdata: dict, job_specs: dict, batch_id: int, update_id # of pending parents if update_id == 1 and len(parent_ids) == 0: state = 'Ready' + time_ready = time_msecs() icr['n_ready_jobs'] += 1 icr['ready_cores_mcpu'] += cores_mcpu if not always_run: @@ -1066,6 +1075,7 @@ async def _create_jobs(userdata: dict, job_specs: dict, batch_id: int, update_id icr['ready_cancellable_cores_mcpu'] += cores_mcpu else: state = 'Pending' + time_ready = None network = spec.get('network') if user != 'ci' and not (network is None or network == 'public'): @@ -1094,6 +1104,8 @@ async def _create_jobs(userdata: dict, job_specs: dict, batch_id: int, update_id ) ) + jobs_telemetry_args.append((batch_id, job_id, time_ready)) + for parent_id in parent_ids: job_parents_args.append((batch_id, job_id, parent_id)) @@ -1138,6 +1150,7 @@ async def insert_jobs_into_db(tx): if err.args[0] == 1062: raise web.HTTPBadRequest(text=f'bunch contains job with duplicated parents ({job_parents_args})') raise + await tx.execute_many( ''' INSERT INTO `job_attributes` (batch_id, job_id, `key`, `value`) @@ -1147,6 +1160,15 @@ async def insert_jobs_into_db(tx): query_name='insert_job_attributes', ) + await tx.execute_many( + ''' +INSERT INTO jobs_telemetry (batch_id, job_id, time_ready) +VALUES (%s, %s, %s); +''', + jobs_telemetry_args, + query_name='insert_jobs_telemetry', + ) + batches_inst_coll_staging_args = [ ( batch_id, @@ -1228,6 +1250,7 @@ async def write_and_insert(tx): @routes.post('/api/v1alpha/batches/create-fast') @auth.rest_authenticated_users_only +@add_metadata_to_request async def create_batch_fast(request, userdata): app = request.app db: Database = app['db'] @@ -1245,11 +1268,13 @@ async def create_batch_fast(request, userdata): return json_response({'id': batch_id}) raise await _commit_update(app, batch_id, update_id, user, db) + request['batch_telemetry']['batch_id'] = str(batch_id) return json_response({'id': batch_id}) @routes.post('/api/v1alpha/batches/create') @auth.rest_authenticated_users_only +@add_metadata_to_request async def create_batch(request, userdata): app = request.app db: Database = app['db'] @@ -1263,6 +1288,7 @@ async def create_batch(request, userdata): ) else: update_id = None + request['batch_telemetry']['batch_id'] = str(id) return json_response({'id': id, 'update_id': update_id}) @@ -1382,6 +1408,7 @@ async def insert(tx): @routes.post('/api/v1alpha/batches/{batch_id}/update-fast') @auth.rest_authenticated_users_only +@add_metadata_to_request async def update_batch_fast(request, userdata): app = request.app db: Database = app['db'] @@ -1408,11 +1435,13 @@ async def update_batch_fast(request, userdata): return json_response({'update_id': update_id, 'start_job_id': start_job_id}) raise await _commit_update(app, batch_id, update_id, user, db) + request['batch_telemetry']['batch_id'] = str(batch_id) return json_response({'update_id': update_id, 'start_job_id': start_job_id}) @routes.post('/api/v1alpha/batches/{batch_id}/updates/create') @auth.rest_authenticated_users_only +@add_metadata_to_request async def create_update(request, userdata): app = request.app db: Database = app['db'] @@ -1569,12 +1598,14 @@ async def _delete_batch(app, batch_id): @routes.get('/api/v1alpha/batches/{batch_id}') @rest_billing_project_users_only +@add_metadata_to_request async def get_batch(request, userdata, batch_id): # pylint: disable=unused-argument return json_response(await _get_batch(request.app, batch_id)) @routes.patch('/api/v1alpha/batches/{batch_id}/cancel') @rest_billing_project_users_only +@add_metadata_to_request async def cancel_batch(request, userdata, batch_id): # pylint: disable=unused-argument await _handle_api_error(_cancel_batch, request.app, batch_id) return web.Response() @@ -1583,6 +1614,7 @@ async def cancel_batch(request, userdata, batch_id): # pylint: disable=unused-a # deprecated @routes.patch('/api/v1alpha/batches/{batch_id}/close') @auth.rest_authenticated_users_only +@add_metadata_to_request async def close_batch(request, userdata): batch_id = int(request.match_info['batch_id']) user = userdata['username'] @@ -1618,6 +1650,7 @@ async def close_batch(request, userdata): @routes.patch('/api/v1alpha/batches/{batch_id}/updates/{update_id}/commit') @auth.rest_authenticated_users_only +@add_metadata_to_request async def commit_update(request: web.Request, userdata): app = request.app db: Database = app['db'] @@ -1672,6 +1705,7 @@ async def _commit_update(app: web.Application, batch_id: int, update_id: int, us @routes.delete('/api/v1alpha/batches/{batch_id}') @rest_billing_project_users_only +@add_metadata_to_request async def delete_batch(request, userdata, batch_id): # pylint: disable=unused-argument await _delete_batch(request.app, batch_id) return web.Response() @@ -1874,6 +1908,7 @@ async def get_attempts(request, userdata, batch_id): # pylint: disable=unused-a @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}') @rest_billing_project_users_only +@add_metadata_to_request async def get_job(request, userdata, batch_id): # pylint: disable=unused-argument job_id = int(request.match_info['job_id']) status = await _get_job(request.app, batch_id, job_id) @@ -2848,14 +2883,17 @@ async def delete_batch_loop_body(app): class BatchFrontEndAccessLogger(AccessLogger): def __init__(self, logger: logging.Logger, log_format: str): super().__init__(logger, log_format) - self.exclude = [ - (endpoint[0], re.compile(deploy_config.base_path('batch') + endpoint[1])) - for endpoint in [ - ('POST', '/api/v1alpha/batches/\\d*/jobs/create'), - ('GET', '/api/v1alpha/batches/\\d*'), - ('GET', '/metrics'), + if DEFAULT_NAMESPACE == 'default': + self.exclude = [ + (endpoint[0], re.compile(deploy_config.base_path('batch') + endpoint[1])) + for endpoint in [ + ('POST', '/api/v1alpha/batches/\\d*/jobs/create'), + ('GET', '/api/v1alpha/batches/\\d*'), + ('GET', '/metrics'), + ] ] - ] + else: + self.exclude = [] def log(self, request, response, time): for method, path_expr in self.exclude: diff --git a/batch/batch/utils.py b/batch/batch/utils.py index aecdaf49f1b..aac9c71d6c1 100644 --- a/batch/batch/utils.py +++ b/batch/batch/utils.py @@ -45,6 +45,24 @@ async def wrapped(request): return wrapped +def add_metadata_to_request(fun): + @wraps(fun) + async def wrapped(request, *args, **kwargs): + request['batch_telemetry'] = {'operation': fun.__name__} + + batch_id = request.match_info.get('batch_id') + if batch_id is not None: + request['batch_telemetry']['batch_id'] = batch_id + + job_id = request.match_info.get('job_id') + if job_id is not None: + request['batch_telemetry']['job_id'] = job_id + + return await fun(request, *args, **kwargs) + + return wrapped + + def coalesce(x, default): if x is not None: return x diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index 0b9848723ab..b746bfd8e50 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -114,11 +114,13 @@ def deeper_stack_level_warn(*args, **kwargs): class BatchWorkerAccessLogger(AccessLogger): def __init__(self, logger: logging.Logger, log_format: str): super().__init__(logger, log_format) - - self.exclude = [ - ('GET', re.compile('/healthcheck')), - ('POST', re.compile('/api/v1alpha/batches/jobs/create')), - ] + if NAMESPACE == 'default': + self.exclude = [ + ('GET', re.compile('/healthcheck')), + ('POST', re.compile('/api/v1alpha/batches/jobs/create')), + ] + else: + self.exclude = [] def log(self, request, response, time): for method, path_expr in self.exclude: @@ -3005,6 +3007,13 @@ async def create_job_1(self, request): assert job_spec['job_id'] == job_id id = (batch_id, job_id) + request['batch_telemetry'] = { + 'operation': 'create_job', + 'batch_id': str(batch_id), + 'job_id': str(job_id), + 'job_queue_time': str(body['queue_time']), + } + # already running if id in self.jobs: return web.HTTPForbidden() @@ -3080,6 +3089,12 @@ async def delete_job_1(self, request): job_id = int(request.match_info['job_id']) id = (batch_id, job_id) + request['batch_telemetry'] = { + 'operation': 'delete_job', + 'batch_id': str(batch_id), + 'job_id': str(job_id), + } + if id not in self.jobs: raise web.HTTPNotFound() diff --git a/batch/sql/add-jobs-ready-time.sql b/batch/sql/add-jobs-ready-time.sql new file mode 100644 index 00000000000..8bc39505aeb --- /dev/null +++ b/batch/sql/add-jobs-ready-time.sql @@ -0,0 +1,213 @@ +CREATE TABLE IF NOT EXISTS `jobs_telemetry` ( + `batch_id` BIGINT NOT NULL, + `job_id` INT NOT NULL, + `time_ready` BIGINT DEFAULT NULL, + PRIMARY KEY (`batch_id`, `job_id`), + FOREIGN KEY (`batch_id`) REFERENCES batches(id) ON DELETE CASCADE +) ENGINE = InnoDB; + +DELIMITER $$ + +DROP PROCEDURE IF EXISTS commit_batch_update $$ +CREATE PROCEDURE commit_batch_update( + IN in_batch_id BIGINT, + IN in_update_id INT, + IN in_timestamp BIGINT +) +BEGIN + DECLARE cur_update_committed BOOLEAN; + DECLARE expected_n_jobs INT; + DECLARE staging_n_jobs INT; + DECLARE cur_update_start_job_id INT; + + START TRANSACTION; + + SELECT committed, n_jobs INTO cur_update_committed, expected_n_jobs + FROM batch_updates + WHERE batch_id = in_batch_id AND update_id = in_update_id + FOR UPDATE; + + IF cur_update_committed THEN + COMMIT; + SELECT 0 as rc; + ELSE + SELECT COALESCE(SUM(n_jobs), 0) INTO staging_n_jobs + FROM batches_inst_coll_staging + WHERE batch_id = in_batch_id AND update_id = in_update_id + FOR UPDATE; + + IF staging_n_jobs = expected_n_jobs THEN + UPDATE batch_updates + SET committed = 1, time_committed = in_timestamp + WHERE batch_id = in_batch_id AND update_id = in_update_id; + + UPDATE batches SET + `state` = 'running', + time_completed = NULL, + n_jobs = n_jobs + expected_n_jobs + WHERE id = in_batch_id; + + INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_ready_jobs, ready_cores_mcpu) + SELECT user, inst_coll, 0, @n_ready_jobs := COALESCE(SUM(n_ready_jobs), 0), @ready_cores_mcpu := COALESCE(SUM(ready_cores_mcpu), 0) + FROM batches_inst_coll_staging + JOIN batches ON batches.id = batches_inst_coll_staging.batch_id + WHERE batch_id = in_batch_id AND update_id = in_update_id + GROUP BY `user`, inst_coll + ON DUPLICATE KEY UPDATE + n_ready_jobs = n_ready_jobs + @n_ready_jobs, + ready_cores_mcpu = ready_cores_mcpu + @ready_cores_mcpu; + + DELETE FROM batches_inst_coll_staging WHERE batch_id = in_batch_id AND update_id = in_update_id; + + IF in_update_id != 1 THEN + SELECT start_job_id INTO cur_update_start_job_id FROM batch_updates WHERE batch_id = in_batch_id AND update_id = in_update_id; + + UPDATE jobs + LEFT JOIN `jobs_telemetry` ON `jobs_telemetry`.batch_id = jobs.batch_id AND `jobs_telemetry`.job_id = jobs.job_id + LEFT JOIN ( + SELECT `job_parents`.batch_id, `job_parents`.job_id, + COALESCE(SUM(1), 0) AS n_parents, + COALESCE(SUM(state IN ('Pending', 'Ready', 'Creating', 'Running')), 0) AS n_pending_parents, + COALESCE(SUM(state = 'Success'), 0) AS n_succeeded + FROM `job_parents` + LEFT JOIN `jobs` ON jobs.batch_id = `job_parents`.batch_id AND jobs.job_id = `job_parents`.parent_id + WHERE job_parents.batch_id = in_batch_id AND + `job_parents`.job_id >= cur_update_start_job_id AND + `job_parents`.job_id < cur_update_start_job_id + staging_n_jobs + GROUP BY `job_parents`.batch_id, `job_parents`.job_id + FOR UPDATE + ) AS t + ON jobs.batch_id = t.batch_id AND + jobs.job_id = t.job_id + SET jobs.state = IF(COALESCE(t.n_pending_parents, 0) = 0, 'Ready', 'Pending'), + jobs.n_pending_parents = COALESCE(t.n_pending_parents, 0), + jobs.cancelled = IF(COALESCE(t.n_succeeded, 0) = COALESCE(t.n_parents - t.n_pending_parents, 0), jobs.cancelled, 1), + jobs_telemetry.time_ready = IF(COALESCE(t.n_pending_parents, 0) = 0 AND jobs_telemetry.time_ready IS NULL, in_timestamp, jobs_telemetry.time_ready) + WHERE jobs.batch_id = in_batch_id AND jobs.job_id >= cur_update_start_job_id AND + jobs.job_id < cur_update_start_job_id + staging_n_jobs; + END IF; + + COMMIT; + SELECT 0 as rc; + ELSE + ROLLBACK; + SELECT 1 as rc, expected_n_jobs, staging_n_jobs as actual_n_jobs, 'wrong number of jobs' as message; + END IF; + END IF; +END $$ + +DROP PROCEDURE IF EXISTS mark_job_complete $$ +CREATE PROCEDURE mark_job_complete( + IN in_batch_id BIGINT, + IN in_job_id INT, + IN in_attempt_id VARCHAR(40), + IN in_instance_name VARCHAR(100), + IN new_state VARCHAR(40), + IN new_status TEXT, + IN new_start_time BIGINT, + IN new_end_time BIGINT, + IN new_reason VARCHAR(40), + IN new_timestamp BIGINT +) +BEGIN + DECLARE cur_job_state VARCHAR(40); + DECLARE cur_instance_state VARCHAR(40); + DECLARE cur_cores_mcpu INT; + DECLARE cur_end_time BIGINT; + DECLARE delta_cores_mcpu INT DEFAULT 0; + DECLARE total_jobs_in_batch INT; + DECLARE expected_attempt_id VARCHAR(40); + + START TRANSACTION; + + SELECT n_jobs INTO total_jobs_in_batch FROM batches WHERE id = in_batch_id; + + SELECT state, cores_mcpu + INTO cur_job_state, cur_cores_mcpu + FROM jobs + WHERE batch_id = in_batch_id AND job_id = in_job_id + FOR UPDATE; + + CALL add_attempt(in_batch_id, in_job_id, in_attempt_id, in_instance_name, cur_cores_mcpu, delta_cores_mcpu); + + SELECT end_time INTO cur_end_time FROM attempts + WHERE batch_id = in_batch_id AND job_id = in_job_id AND attempt_id = in_attempt_id + FOR UPDATE; + + UPDATE attempts + SET start_time = new_start_time, rollup_time = new_end_time, end_time = new_end_time, reason = new_reason + WHERE batch_id = in_batch_id AND job_id = in_job_id AND attempt_id = in_attempt_id; + + SELECT state INTO cur_instance_state FROM instances WHERE name = in_instance_name LOCK IN SHARE MODE; + IF cur_instance_state = 'active' AND cur_end_time IS NULL THEN + UPDATE instances_free_cores_mcpu + SET free_cores_mcpu = free_cores_mcpu + cur_cores_mcpu + WHERE instances_free_cores_mcpu.name = in_instance_name; + + SET delta_cores_mcpu = delta_cores_mcpu + cur_cores_mcpu; + END IF; + + SELECT attempt_id INTO expected_attempt_id FROM jobs + WHERE batch_id = in_batch_id AND job_id = in_job_id + FOR UPDATE; + + IF expected_attempt_id IS NOT NULL AND expected_attempt_id != in_attempt_id THEN + COMMIT; + SELECT 2 as rc, + expected_attempt_id, + delta_cores_mcpu, + 'input attempt id does not match expected attempt id' as message; + ELSEIF cur_job_state = 'Ready' OR cur_job_state = 'Creating' OR cur_job_state = 'Running' THEN + UPDATE jobs + SET state = new_state, status = new_status, attempt_id = in_attempt_id + WHERE batch_id = in_batch_id AND job_id = in_job_id; + + UPDATE batches_n_jobs_in_complete_states + SET n_completed = (@new_n_completed := n_completed + 1), + n_cancelled = n_cancelled + (new_state = 'Cancelled'), + n_failed = n_failed + (new_state = 'Error' OR new_state = 'Failed'), + n_succeeded = n_succeeded + (new_state != 'Cancelled' AND new_state != 'Error' AND new_state != 'Failed') + WHERE id = in_batch_id; + + # Grabbing an exclusive lock on batches here could deadlock, + # but this IF should only execute for the last job + IF @new_n_completed = total_jobs_in_batch THEN + UPDATE batches + SET time_completed = new_timestamp, + `state` = 'complete' + WHERE id = in_batch_id; + END IF; + + UPDATE jobs + LEFT JOIN `jobs_telemetry` ON `jobs_telemetry`.batch_id = jobs.batch_id AND `jobs_telemetry`.job_id = jobs.job_id + INNER JOIN `job_parents` + ON jobs.batch_id = `job_parents`.batch_id AND + jobs.job_id = `job_parents`.job_id + SET jobs.state = IF(jobs.n_pending_parents = 1, 'Ready', 'Pending'), + jobs.n_pending_parents = jobs.n_pending_parents - 1, + jobs.cancelled = IF(new_state = 'Success', jobs.cancelled, 1), + jobs_telemetry.time_ready = IF(jobs.n_pending_parents = 1, new_timestamp, jobs_telemetry.time_ready) + WHERE jobs.batch_id = in_batch_id AND + `job_parents`.batch_id = in_batch_id AND + `job_parents`.parent_id = in_job_id; + + COMMIT; + SELECT 0 as rc, + cur_job_state as old_state, + delta_cores_mcpu; + ELSEIF cur_job_state = 'Cancelled' OR cur_job_state = 'Error' OR + cur_job_state = 'Failed' OR cur_job_state = 'Success' THEN + COMMIT; + SELECT 0 as rc, + cur_job_state as old_state, + delta_cores_mcpu; + ELSE + COMMIT; + SELECT 1 as rc, + cur_job_state, + delta_cores_mcpu, + 'job state not Ready, Creating, Running or complete' as message; + END IF; +END $$ + +DELIMITER ; diff --git a/batch/sql/estimated-current.sql b/batch/sql/estimated-current.sql index aed88292d51..6172b147b60 100644 --- a/batch/sql/estimated-current.sql +++ b/batch/sql/estimated-current.sql @@ -274,6 +274,14 @@ CREATE INDEX `jobs_batch_id_update_id` ON `jobs` (`batch_id`, `update_id`); CREATE INDEX `jobs_batch_id_always_run_n_regions_regions_bits_rep_job_id` ON `jobs` (`batch_id`, `always_run`, `n_regions`, `regions_bits_rep`, `job_id`); CREATE INDEX `jobs_batch_id_ic_state_ar_n_regions_bits_rep_job_id` ON `jobs` (`batch_id`, `inst_coll`, `state`, `always_run`, `n_regions`, `regions_bits_rep`, `job_id`); +CREATE TABLE IF NOT EXISTS `jobs_telemetry` ( + `batch_id` BIGINT NOT NULL, + `job_id` INT NOT NULL, + `time_ready` BIGINT DEFAULT NULL, + PRIMARY KEY (`batch_id`, `job_id`), + FOREIGN KEY (`batch_id`) REFERENCES batches(id) ON DELETE CASCADE +) ENGINE = InnoDB; + CREATE TABLE IF NOT EXISTS `batch_bunches` ( `batch_id` BIGINT NOT NULL, `start_job_id` INT NOT NULL, @@ -1219,6 +1227,7 @@ BEGIN SELECT start_job_id INTO cur_update_start_job_id FROM batch_updates WHERE batch_id = in_batch_id AND update_id = in_update_id; UPDATE jobs + LEFT JOIN `jobs_telemetry` ON `jobs_telemetry`.batch_id = jobs.batch_id AND `jobs_telemetry`.job_id = jobs.job_id LEFT JOIN ( SELECT `job_parents`.batch_id, `job_parents`.job_id, COALESCE(SUM(1), 0) AS n_parents, @@ -1236,7 +1245,8 @@ BEGIN jobs.job_id = t.job_id SET jobs.state = IF(COALESCE(t.n_pending_parents, 0) = 0, 'Ready', 'Pending'), jobs.n_pending_parents = COALESCE(t.n_pending_parents, 0), - jobs.cancelled = IF(COALESCE(t.n_succeeded, 0) = COALESCE(t.n_parents - t.n_pending_parents, 0), jobs.cancelled, 1) + jobs.cancelled = IF(COALESCE(t.n_succeeded, 0) = COALESCE(t.n_parents - t.n_pending_parents, 0), jobs.cancelled, 1), + jobs_telemetry.time_ready = IF(COALESCE(t.n_pending_parents, 0) = 0 AND jobs_telemetry.time_ready IS NULL, in_timestamp, jobs_telemetry.time_ready) WHERE jobs.batch_id = in_batch_id AND jobs.job_id >= cur_update_start_job_id AND jobs.job_id < cur_update_start_job_id + staging_n_jobs; END IF; @@ -1711,12 +1721,14 @@ BEGIN END IF; UPDATE jobs + LEFT JOIN `jobs_telemetry` ON `jobs_telemetry`.batch_id = jobs.batch_id AND `jobs_telemetry`.job_id = jobs.job_id INNER JOIN `job_parents` ON jobs.batch_id = `job_parents`.batch_id AND jobs.job_id = `job_parents`.job_id SET jobs.state = IF(jobs.n_pending_parents = 1, 'Ready', 'Pending'), jobs.n_pending_parents = jobs.n_pending_parents - 1, - jobs.cancelled = IF(new_state = 'Success', jobs.cancelled, 1) + jobs.cancelled = IF(new_state = 'Success', jobs.cancelled, 1), + jobs_telemetry.time_ready = IF(jobs.n_pending_parents = 1, new_timestamp, jobs_telemetry.time_ready) WHERE jobs.batch_id = in_batch_id AND `job_parents`.batch_id = in_batch_id AND `job_parents`.parent_id = in_job_id; diff --git a/build.yaml b/build.yaml index d9c31378f88..a2a673aa8ee 100644 --- a/build.yaml +++ b/build.yaml @@ -2269,6 +2269,9 @@ steps: - name: dedup-billing-project-users-by-date script: /io/sql/dedup_billing_project_users_by_date.py online: true + - name: add-jobs-ready-time + script: /io/sql/add-jobs-ready-time.sql + online: true inputs: - from: /repo/batch/sql to: /io/sql diff --git a/hail/python/hailtop/hail_logging.py b/hail/python/hailtop/hail_logging.py index b69db4b6480..34cd21a62da 100644 --- a/hail/python/hailtop/hail_logging.py +++ b/hail/python/hailtop/hail_logging.py @@ -51,10 +51,15 @@ def log(self, request, response, time): now = datetime.datetime.now(tz) start_time = now - datetime.timedelta(seconds=time) start_time_str = start_time.strftime('[%d/%b/%Y:%H:%M:%S %z]') + + extra = { + 'remote_address': request.remote, + 'request_start_time': start_time_str, + 'request_duration': time, + 'response_status': response.status, + 'x_real_ip': request.headers.get("X-Real-IP") + } + self.logger.info(f'{request.scheme} {request.method} {request.path} ' f'done in {time}s: {response.status}', - extra={'remote_address': request.remote, - 'request_start_time': start_time_str, - 'request_duration': time, - 'response_status': response.status, - 'x_real_ip': request.headers.get("X-Real-IP")}) + extra={**extra, **request.get('batch_telemetry', {})}) From 71ea01205d9262d3ead9492f67d0d14425a9c871 Mon Sep 17 00:00:00 2001 From: Tim Poterba Date: Thu, 29 Jun 2023 12:16:20 -0400 Subject: [PATCH 002/180] [query] Fix BAD loop deoptimization with StreamAgg (#12995) CHANGELOG: Fixed bug causing poor performance and memory leaks for Matrix.annotate_rows aggregations --------- Co-authored-by: patrick-schultz --- .../main/scala/is/hail/expr/ir/NestingDepth.scala | 15 ++++++++++++++- .../scala/is/hail/expr/ir/ForwardLetsSuite.scala | 8 +++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala b/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala index 75e52e1630d..2754e0b645e 100644 --- a/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala +++ b/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala @@ -39,11 +39,24 @@ object NestingDepth { def computeBlockMatrix(bmir: BlockMatrixIR): Unit = computeChildren(bmir) def computeIR(ir: IR, depth: ScopedDepth): Unit = { - memo.bind(ir, depth.eval) + ir match { + case x@AggLet(_, _, _, false) => + memo.bind(x, depth.agg) + case x@AggLet(_, _, _, true) => + memo.bind(x, depth.scan) + case _ => + memo.bind(ir, depth.eval) + } ir match { case StreamMap(a, name, body) => computeIR(a, depth) computeIR(body, depth.incrementEval) + case StreamAgg(a, name, body) => + computeIR(a, depth) + computeIR(body, ScopedDepth(depth.eval, depth.eval + 1, depth.scan)) + case StreamAggScan(a, name, body) => + computeIR(a, depth) + computeIR(body, ScopedDepth(depth.eval, depth.agg, depth.eval + 1)) case StreamZip(as, _, body, _, _) => as.foreach(computeIR(_, depth)) computeIR(body, depth.incrementEval) diff --git a/hail/src/test/scala/is/hail/expr/ir/ForwardLetsSuite.scala b/hail/src/test/scala/is/hail/expr/ir/ForwardLetsSuite.scala index 1d1bcb2828e..cc4391f4c85 100644 --- a/hail/src/test/scala/is/hail/expr/ir/ForwardLetsSuite.scala +++ b/hail/src/test/scala/is/hail/expr/ir/ForwardLetsSuite.scala @@ -23,7 +23,8 @@ class ForwardLetsSuite extends HailSuite { ToArray(StreamScan(ToStream(a), I32(0), "acc", "y", ApplyBinaryPrimOp(Add(), ApplyBinaryPrimOp(Add(), x, y), Ref("acc", TInt32)))), MakeStruct(FastSeq("a" -> ApplyBinaryPrimOp(Add(), x, I32(1)), "b" -> ApplyBinaryPrimOp(Add(), x, I32(2)))), MakeTuple.ordered(FastSeq(ApplyBinaryPrimOp(Add(), x, I32(1)), ApplyBinaryPrimOp(Add(), x, I32(2)))), - ApplyBinaryPrimOp(Add(), ApplyBinaryPrimOp(Add(), x, x), I32(1)) + ApplyBinaryPrimOp(Add(), ApplyBinaryPrimOp(Add(), x, x), I32(1)), + StreamAgg(ToStream(a), "y", ApplyAggOp(Sum())(x + y)) ).map(ir => Array[IR](Let("x", In(0, TInt32) + In(0, TInt32), ir))) } @@ -85,8 +86,9 @@ class ForwardLetsSuite extends HailSuite { @Test(dataProvider = "nonForwardingOps") def testNonForwardingOps(ir: IR): Unit = { val after = ForwardLets(ir) - assert(after.isInstanceOf[Let]) - assertEvalSame(ir, args = Array(5 -> TInt32)) + val normalizedBefore = (new NormalizeNames(_.toString)).apply(ir) + val normalizedAfter = (new NormalizeNames(_.toString)).apply(after) + assert(normalizedBefore == normalizedAfter) } @Test(dataProvider = "nonForwardingNonEvalOps") From 245dfdd75eb98f2f7a77145b182a82582f4b28ba Mon Sep 17 00:00:00 2001 From: jigold Date: Thu, 29 Jun 2023 17:24:53 -0400 Subject: [PATCH 003/180] [ci] Add merge candidate to UI page (#13217) --- ci/ci/ci.py | 2 ++ ci/ci/github.py | 6 ++++++ ci/ci/templates/index.html | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/ci/ci/ci.py b/ci/ci/ci.py index 6d1a67398ca..a8fd881c97c 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -105,6 +105,7 @@ class WatchedBranchConfig(TypedDict): repo: str prs: List[PRConfig] gh_status_names: Set[str] + merge_candidate: Optional[str] async def watched_branch_config(app, wb: WatchedBranch, index: int) -> WatchedBranchConfig: @@ -124,6 +125,7 @@ async def watched_branch_config(app, wb: WatchedBranch, index: int) -> WatchedBr 'repo': wb.branch.repo.short_str(), 'prs': pr_configs, 'gh_status_names': gh_status_names, + 'merge_candidate': wb.merge_candidate.short_str() if wb.merge_candidate else None, } diff --git a/ci/ci/github.py b/ci/ci/github.py index 72f561ea737..9161b2fa212 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -689,6 +689,8 @@ def __init__(self, index, branch, deployable, mergeable): self.n_running_batches: int = 0 + self.merge_candidate: Optional[PR] = None + @property def deploy_state(self): return self._deploy_state @@ -770,6 +772,7 @@ async def try_to_merge(self, gh): self.github_changed = True self.sha = None self.state_changed = True + self.merge_candidate = None return async def _update_github(self, gh): @@ -892,6 +895,9 @@ async def _heal(self, app, batch_client, gh): if is_authorized and (not merge_candidate or pri > merge_candidate_pri): merge_candidate = pr merge_candidate_pri = pri + + self.merge_candidate = merge_candidate + if merge_candidate: log.info(f'merge candidate {merge_candidate.number}') diff --git a/ci/ci/templates/index.html b/ci/ci/templates/index.html index f3917be9baa..1694005c760 100644 --- a/ci/ci/templates/index.html +++ b/ci/ci/templates/index.html @@ -27,6 +27,11 @@

{{ wb.branch }}

{{ wb.deploy_batch_id }} {% endif %} +
Merge Candidate: + {% if wb.merge_candidate is not none %} + {{ wb.merge_candidate }} + {% endif %} +
From d53a26623c0aaaa4894cc86a906ec86537d07834 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 29 Jun 2023 18:25:09 -0400 Subject: [PATCH 004/180] [auth] Only resolve the identity UID for active users (#13221) For deleted users the request to look up the AAD application can fail with a 404, and we don't need to gather this information for deleted users anyway. --- auth/auth/driver/driver.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/auth/auth/driver/driver.py b/auth/auth/driver/driver.py index fb5a698a3ad..daa6a4ebe9d 100644 --- a/auth/auth/driver/driver.py +++ b/auth/auth/driver/driver.py @@ -547,7 +547,10 @@ async def update_users(app): await delete_user(app, user) users_without_hail_identity_uid = [ - x async for x in db.execute_and_fetchall('SELECT * FROM users WHERE hail_identity_uid IS NULL') + x + async for x in db.execute_and_fetchall( + "SELECT * FROM users WHERE state = 'active' AND hail_identity_uid IS NULL" + ) ] for user in users_without_hail_identity_uid: await resolve_identity_uid(app, user['hail_identity']) From b910be302c93fed089b20050e3dec2976f2c08d4 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 30 Jun 2023 10:12:52 -0400 Subject: [PATCH 005/180] [ci] Add test identities for services in test namespaces (#13202) Identities in test namespaces cannot share the same underlying cloud identity if we want to identify requests with cloud access tokens. This also means the `test` account does not need to have the union of roles of the other robot accounts, but pruning of the `test` account's roles is left until after this PR merges so we can properly assess which roles are still in use by the `test` account. --- build.yaml | 29 ++++--- infra/azure/modules/auth/main.tf | 21 +++++ infra/azure/modules/batch/main.tf | 135 +++++++++++++++++++++++++++++- infra/gcp-broad/main.tf | 130 ++++++++++++++++++++++++++++ infra/gcp/main.tf | 122 ++++++++++++++++++++++++++- 5 files changed, 422 insertions(+), 15 deletions(-) diff --git a/build.yaml b/build.yaml index a2a673aa8ee..c0130d9ae73 100644 --- a/build.yaml +++ b/build.yaml @@ -41,7 +41,12 @@ steps: - name: auth-oauth2-client-secret - name: registry-push-credentials - name: hail-ci-0-1-github-oauth-token - - name: test-gsa-key + - name: testns-test-gsa-key + - name: testns-test-dev-gsa-key + - name: testns-auth-gsa-key + - name: testns-batch-gsa-key + - name: testns-ci-gsa-key + - name: testns-grafana-gsa-key - name: test-aws-key clouds: - gcp @@ -479,11 +484,12 @@ steps: image: valueFrom: ci_utils_image.image script: | - kubectl -n {{ default_ns.name }} get -o json secret test-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "auth-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - - kubectl -n {{ default_ns.name }} get -o json secret test-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "batch-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - - kubectl -n {{ default_ns.name }} get -o json secret test-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "ci-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - - kubectl -n {{ default_ns.name }} get -o json secret test-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "test-dev-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - - kubectl -n {{ default_ns.name }} get -o json secret test-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "grafana-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - + kubectl -n {{ default_ns.name }} get -o json secret testns-test-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "test-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - + kubectl -n {{ default_ns.name }} get -o json secret testns-test-dev-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "test-dev-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - + kubectl -n {{ default_ns.name }} get -o json secret testns-auth-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "auth-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - + kubectl -n {{ default_ns.name }} get -o json secret testns-batch-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "batch-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - + kubectl -n {{ default_ns.name }} get -o json secret testns-ci-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "ci-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - + kubectl -n {{ default_ns.name }} get -o json secret testns-grafana-gsa-key | jq '{apiVersion, kind, type, data, metadata: {name: "grafana-gsa-key"}}' | kubectl -n {{ default_ns.name }} apply -f - scopes: - test - dev @@ -940,6 +946,7 @@ steps: dependsOn: - default_ns - hailgenetics_hailtop_image + - create_test_gsa_keys - merge_code - kind: runImage name: test_hail_java @@ -3771,9 +3778,9 @@ steps: alwaysRun: true script: | set -e -o pipefail - AZURE_USERNAME=$(jq -r '.appId' /test-gsa-key/key.json) - AZURE_PASSWORD=$(jq -r '.password' /test-gsa-key/key.json) - AZURE_TENANT_ID=$(jq -r '.tenant' /test-gsa-key/key.json) + AZURE_USERNAME=$(jq -r '.appId' /batch-gsa-key/key.json) + AZURE_PASSWORD=$(jq -r '.password' /batch-gsa-key/key.json) + AZURE_TENANT_ID=$(jq -r '.tenant' /batch-gsa-key/key.json) az login --service-principal -u $AZURE_USERNAME -p $AZURE_PASSWORD --tenant $AZURE_TENANT_ID set +e set -x @@ -3793,10 +3800,10 @@ steps: --query "[?tags.namespace == '{{ default_ns.name }}'].name" \ | xargs -n1 -r sh -c 'az deployment delete --name "$1" || true' argv0 secrets: - - name: test-gsa-key + - name: batch-gsa-key namespace: valueFrom: default_ns.name - mountPath: /test-gsa-key + mountPath: /batch-gsa-key scopes: - dev - test diff --git a/infra/azure/modules/auth/main.tf b/infra/azure/modules/auth/main.tf index d793ebcb500..ced783e2727 100644 --- a/infra/azure/modules/auth/main.tf +++ b/infra/azure/modules/auth/main.tf @@ -21,6 +21,27 @@ module "auth_sp" { application_object_id = azuread_application.auth.object_id } +resource "azuread_application" "testns_auth" { + display_name = "${var.resource_group_name}-testns-auth" + + required_resource_access { + resource_app_id = "00000003-0000-0000-c000-000000000000" + + resource_access { + # Application.ReadWrite.All + id = "1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9" + type = "Role" + } + } +} +module "testns_auth_sp" { + source = "../service_principal" + + name = "testns-auth" + application_id = azuread_application.testns_auth.application_id + application_object_id = azuread_application.testns_auth.object_id +} + resource "azuread_application" "oauth2" { display_name = "${var.resource_group_name}-oauth2" diff --git a/infra/azure/modules/batch/main.tf b/infra/azure/modules/batch/main.tf index 4f279d741d1..5e6245ecefb 100644 --- a/infra/azure/modules/batch/main.tf +++ b/infra/azure/modules/batch/main.tf @@ -175,6 +175,38 @@ resource "azurerm_role_assignment" "batch_test_container_contributor" { principal_id = module.batch_sp.principal_id } +resource "azuread_application" "testns_batch" { + display_name = "${var.resource_group.name}-testns-batch" +} +module "testns_batch_sp" { + source = "../service_principal" + + name = "testns-batch" + application_id = azuread_application.testns_batch.application_id + application_object_id = azuread_application.testns_batch.object_id + + subscription_resource_id = data.azurerm_subscription.primary.id + subscription_roles = [ + "Reader", + "Virtual Machine Contributor", + ] + + resource_group_id = var.resource_group.id + resource_group_roles = [ + "Network Contributor", + "Managed Identity Operator", + "Log Analytics Contributor", + ] +} + +resource "azurerm_role_assignment" "testns_batch_test_container_contributor" { + scope = azurerm_storage_container.test.resource_manager_id + role_definition_name = "Storage Blob Data Contributor" + principal_id = module.testns_batch_sp.principal_id +} + +# FIXME Now that there are test identities for each service, the test user no longer +# needs this many permissions. Perform an audit to see which can be removed resource "azuread_application" "test" { display_name = "${var.resource_group.name}-test" @@ -209,12 +241,48 @@ module "test_sp" { ] } -resource "azurerm_role_assignment" "test_test_container_contributor" { +resource "azurerm_role_assignment" "test_sp_test_container_contributor" { scope = azurerm_storage_container.test.resource_manager_id role_definition_name = "Storage Blob Data Contributor" principal_id = module.test_sp.principal_id } +resource "azurerm_role_assignment" "test_sp_registry_viewer" { + scope = var.container_registry_id + role_definition_name = "AcrPull" + principal_id = module.test_sp.principal_id +} + +resource "azuread_application" "testns_test" { + display_name = "${var.resource_group.name}-testns-test" +} +module "testns_test_sp" { + source = "../service_principal" + + name = "testns-test" + application_id = azuread_application.testns_test.application_id + application_object_id = azuread_application.testns_test.object_id +} + +resource "azurerm_role_assignment" "testns_test_sp_test_container_contributor" { + scope = azurerm_storage_container.test.resource_manager_id + role_definition_name = "Storage Blob Data Contributor" + principal_id = module.testns_test_sp.principal_id +} + +# Necessary to generate SAS tokens +resource "azurerm_role_assignment" "testns_test_sp_test_account_key_operator" { + scope = azurerm_storage_account.test.id + role_definition_name = "Storage Account Key Operator Service Role" + principal_id = module.testns_test_sp.principal_id +} + +resource "azurerm_role_assignment" "testns_test_sp_registry_viewer" { + scope = var.container_registry_id + role_definition_name = "AcrPull" + principal_id = module.testns_test_sp.principal_id +} + resource "azuread_application" "ci" { display_name = "${var.resource_group.name}-ci" } @@ -225,6 +293,7 @@ module "ci_sp" { application_id = azuread_application.ci.application_id application_object_id = azuread_application.ci.object_id } + resource "azurerm_role_assignment" "ci_acr_role" { for_each = toset(["AcrPush", "AcrDelete"]) @@ -232,6 +301,7 @@ resource "azurerm_role_assignment" "ci_acr_role" { role_definition_name = each.key principal_id = module.ci_sp.principal_id } + resource "kubernetes_secret" "registry_push_credentials" { metadata { name = "registry-push-credentials" @@ -242,6 +312,30 @@ resource "kubernetes_secret" "registry_push_credentials" { } } +resource "azuread_application" "testns_ci" { + display_name = "${var.resource_group.name}-testns-ci" +} +module "testns_ci_sp" { + source = "../service_principal" + + name = "testns-ci" + application_id = azuread_application.testns_ci.application_id + application_object_id = azuread_application.testns_ci.object_id +} + +resource "azurerm_role_assignment" "testns_ci_test_container_contributor" { + scope = azurerm_storage_container.test.resource_manager_id + role_definition_name = "Storage Blob Data Contributor" + principal_id = module.testns_ci_sp.principal_id +} + +resource "azurerm_role_assignment" "testns_ci_acr_role" { + for_each = toset(["AcrPush", "AcrDelete"]) + + scope = var.container_registry_id + role_definition_name = each.key + principal_id = module.testns_ci_sp.principal_id +} resource "azuread_application" "test_dev" { display_name = "${var.resource_group.name}-test-dev" @@ -254,6 +348,29 @@ module "test_dev_sp" { application_object_id = azuread_application.test_dev.object_id } +resource "azurerm_role_assignment" "test_dev_registry_viewer" { + scope = var.container_registry_id + role_definition_name = "AcrPull" + principal_id = module.test_dev_sp.principal_id +} + +resource "azuread_application" "testns_test_dev" { + display_name = "${var.resource_group.name}-testns-test-dev" +} +module "testns_test_dev_sp" { + source = "../service_principal" + + name = "testns-test-dev" + application_id = azuread_application.testns_test_dev.application_id + application_object_id = azuread_application.testns_test_dev.object_id +} + +resource "azurerm_role_assignment" "testns_test_dev_registry_viewer" { + scope = var.container_registry_id + role_definition_name = "AcrPull" + principal_id = module.testns_test_dev_sp.principal_id +} + resource "azuread_application" "grafana" { display_name = "${var.resource_group.name}-grafana" } @@ -269,3 +386,19 @@ module "grafana_sp" { "Monitoring Reader", ] } + +resource "azuread_application" "testns_grafana" { + display_name = "${var.resource_group.name}-testns-grafana" +} +module "testns_grafana_sp" { + source = "../service_principal" + + name = "testns-grafana" + application_id = azuread_application.testns_grafana.application_id + application_object_id = azuread_application.testns_grafana.object_id + + resource_group_id = var.resource_group.id + resource_group_roles = [ + "Monitoring Reader", + ] +} diff --git a/infra/gcp-broad/main.tf b/infra/gcp-broad/main.tf index cc36c4d550c..a527a8f0bb8 100644 --- a/infra/gcp-broad/main.tf +++ b/infra/gcp-broad/main.tf @@ -461,6 +461,15 @@ module "auth_gsa_secret" { ] } +module "testns_auth_gsa_secret" { + source = "./gsa" + name = "testns-auth" + project = var.gcp_project + iam_roles = [ + "iam.serviceAccountViewer", + ] +} + module "batch_gsa_secret" { source = "./gsa" name = "batch" @@ -478,6 +487,23 @@ resource "google_storage_bucket_iam_member" "batch_hail_query_bucket_storage_vie member = "serviceAccount:${module.batch_gsa_secret.email}" } +module "testns_batch_gsa_secret" { + source = "./gsa" + name = "testns-batch" + project = var.gcp_project + iam_roles = [ + "compute.instanceAdmin.v1", + "iam.serviceAccountUser", + "logging.viewer", + ] +} + +resource "google_storage_bucket_iam_member" "testns_batch_bucket_admin" { + bucket = google_storage_bucket.hail_test_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_batch_gsa_secret.email}" +} + module "ci_gsa_secret" { source = "./gsa" name = "ci" @@ -493,12 +519,41 @@ resource "google_artifact_registry_repository_iam_member" "artifact_registry_vie member = "serviceAccount:${module.ci_gsa_secret.email}" } +module "testns_ci_gsa_secret" { + source = "./gsa" + name = "testns-ci" + project = var.gcp_project +} + +resource "google_storage_bucket_iam_member" "testns_ci_bucket_admin" { + bucket = google_storage_bucket.hail_test_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_ci_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_testns_ci_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.artifact_registry_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.testns_ci_gsa_secret.email}" +} + module "grafana_gsa_secret" { source = "./gsa" name = "grafana" project = var.gcp_project } +module "testns_grafana_gsa_secret" { + source = "./gsa" + name = "testns-grafana" + project = var.gcp_project +} + +# FIXME Now that there are test identities for each service, the test user no longer +# needs this many permissions. Perform an audit to see which can be removed module "test_gsa_secret" { source = "./gsa" name = "test" @@ -517,6 +572,51 @@ resource "google_storage_bucket_iam_member" "test_bucket_admin" { member = "serviceAccount:${module.test_gsa_secret.email}" } +resource "google_storage_bucket_iam_member" "test_requester_pays_bucket_admin" { + bucket = google_storage_bucket.hail_test_requester_pays_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.test_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_test_gsa_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.artifact_registry_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.test_gsa_secret.email}" +} + +module "testns_test_gsa_secret" { + source = "./gsa" + name = "testns-test" + project = var.gcp_project + iam_roles = [ + "serviceusage.serviceUsageConsumer", + ] +} + +resource "google_storage_bucket_iam_member" "testns_test_gsa_bucket_admin" { + bucket = google_storage_bucket.hail_test_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_test_gsa_secret.email}" +} + +resource "google_storage_bucket_iam_member" "testns_test_gsa_requester_pays_bucket_admin" { + bucket = google_storage_bucket.hail_test_requester_pays_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_test_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_testns_test_gsa_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.artifact_registry_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.testns_test_gsa_secret.email}" +} + module "test_dev_gsa_secret" { source = "./gsa" name = "test-dev" @@ -529,6 +629,36 @@ resource "google_storage_bucket_iam_member" "test_dev_bucket_admin" { member = "serviceAccount:${module.test_dev_gsa_secret.email}" } +resource "google_artifact_registry_repository_iam_member" "artifact_registry_test_dev_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.artifact_registry_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.test_dev_gsa_secret.email}" +} + +module "testns_test_dev_gsa_secret" { + source = "./gsa" + name = "testns-test-dev" + project = var.gcp_project +} + +resource "google_storage_bucket_iam_member" "testns_test_dev_bucket_admin" { + bucket = google_storage_bucket.hail_test_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_test_dev_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_testns_test_dev_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.artifact_registry_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.testns_test_dev_gsa_secret.email}" +} + resource "google_service_account" "batch_agent" { description = "Delete instances and pull images" display_name = "batch2-agent" diff --git a/infra/gcp/main.tf b/infra/gcp/main.tf index 40a791ac12b..4629cd550ed 100644 --- a/infra/gcp/main.tf +++ b/infra/gcp/main.tf @@ -440,6 +440,15 @@ module "auth_gsa_secret" { ] } +module "testns_auth_gsa_secret" { + source = "./gsa_k8s_secret" + name = "testns-auth" + project = var.gcp_project + iam_roles = [ + "iam.serviceAccountViewer", + ] +} + module "batch_gsa_secret" { source = "./gsa_k8s_secret" name = "batch" @@ -458,12 +467,50 @@ resource "google_storage_bucket_iam_member" "batch_hail_query_bucket_storage_vie member = "serviceAccount:${module.batch_gsa_secret.email}" } +module "testns_batch_gsa_secret" { + source = "./gsa_k8s_secret" + name = "testns-batch" + project = var.gcp_project + iam_roles = [ + "compute.instanceAdmin.v1", + "iam.serviceAccountUser", + "logging.viewer", + ] +} + +resource "google_storage_bucket_iam_member" "testns_batch_bucket_admin" { + bucket = google_storage_bucket.hail_test_gcs_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_batch_gsa_secret.email}" +} + module "ci_gsa_secret" { source = "./gsa_k8s_secret" name = "ci" project = var.gcp_project } +module "testns_ci_gsa_secret" { + source = "./gsa_k8s_secret" + name = "testns-ci" + project = var.gcp_project +} + +resource "google_storage_bucket_iam_member" "testns_ci_bucket_admin" { + bucket = google_storage_bucket.hail_test_gcs_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_ci_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_testns_ci_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.gcp_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.testns_ci_gsa_secret.email}" +} + resource "google_artifact_registry_repository_iam_member" "artifact_registry_viewer" { provider = google-beta project = var.gcp_project @@ -485,6 +532,14 @@ module "grafana_gsa_secret" { project = var.gcp_project } +module "testns_grafana_gsa_secret" { + source = "./gsa_k8s_secret" + name = "testns-grafana" + project = var.gcp_project +} + +# FIXME Now that there are test identities for each service, the test user no longer +# needs this many permissions. Perform an audit to see which can be removed module "test_gsa_secret" { source = "./gsa_k8s_secret" name = "test" @@ -503,18 +558,79 @@ resource "google_storage_bucket_iam_member" "test_bucket_admin" { member = "serviceAccount:${module.test_gsa_secret.email}" } -resource "google_storage_bucket_iam_member" "test_gcr_viewer" { - bucket = google_container_registry.registry.id - role = "roles/storage.objectViewer" +resource "google_artifact_registry_repository_iam_member" "artifact_registry_test_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.gcp_location + role = "roles/artifactregistry.reader" member = "serviceAccount:${module.test_gsa_secret.email}" } +module "testns_test_gsa_secret" { + source = "./gsa_k8s_secret" + name = "testns-test" + project = var.gcp_project +} + +resource "google_storage_bucket_iam_member" "testns_test_gsa_bucket_admin" { + bucket = module.hail_test_gcs_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_test_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_testns_test_gsa_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.gcp_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.testns_test_gsa_secret.email}" +} + + module "test_dev_gsa_secret" { source = "./gsa_k8s_secret" name = "test-dev" project = var.gcp_project } +resource "google_storage_bucket_iam_member" "test_dev_bucket_admin" { + bucket = google_storage_bucket.hail_test_gcs_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.test_dev_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_test_dev_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.gcp_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.test_dev_gsa_secret.email}" +} + +module "testns_test_dev_gsa_secret" { + source = "./gsa_k8s_secret" + name = "testns-test-dev" + project = var.gcp_project +} + +resource "google_storage_bucket_iam_member" "testns_test_dev_bucket_admin" { + bucket = google_storage_bucket.hail_test_gcs_bucket.name + role = "roles/storage.admin" + member = "serviceAccount:${module.testns_test_dev_gsa_secret.email}" +} + +resource "google_artifact_registry_repository_iam_member" "artifact_registry_testns_test_dev_viewer" { + provider = google-beta + project = var.gcp_project + repository = google_artifact_registry_repository.repository.name + location = var.gcp_location + role = "roles/artifactregistry.reader" + member = "serviceAccount:${module.testns_test_dev_gsa_secret.email}" +} + resource "google_service_account" "batch_agent" { account_id = "batch2-agent" } From 8d6b171f05b8f79f4ef63c73593fb789bd86c766 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Wed, 5 Jul 2023 09:29:00 -0500 Subject: [PATCH 006/180] [query/vds] Rework VDS combiner so that it can run via Query on Batch (#13206) Key changes: - Remove old VCF combiner - Add StreamZipJoinProducers an IR that takes an array, and a function from array.elementType to stream and zip joins the result of calling that function on each member of the array. - Combine Table._generate and this new stream zip operation to rewrite the gvcf merge stage of the vds combiner in O(1) IR --------- Co-authored-by: Tim Poterba --- .../cluster-tests/cluster-read-vcfs-check.py | 23 - hail/python/hail/docs/experimental/index.rst | 1 - .../hail/docs/experimental/vcf_combiner.rst | 220 ------ hail/python/hail/docs/methods/impex.rst | 2 - hail/python/hail/docs/methods/index.rst | 1 - hail/python/hail/experimental/__init__.py | 4 +- .../{vcf_combiner => sparse_mt}/__init__.py | 4 - .../{vcf_combiner => sparse_mt}/densify.py | 0 .../sparse_split_multi.py | 0 .../experimental/vcf_combiner/__main__.py | 62 -- .../experimental/vcf_combiner/vcf_combiner.py | 744 ------------------ hail/python/hail/expr/__init__.py | 3 +- hail/python/hail/expr/functions.py | 26 + hail/python/hail/expr/type_parsing.py | 88 +++ hail/python/hail/ir/__init__.py | 12 +- hail/python/hail/ir/base_ir.py | 22 - hail/python/hail/ir/ir.py | 162 +++- hail/python/hail/ir/matrix_ir.py | 15 - hail/python/hail/ir/register_functions.py | 9 + hail/python/hail/methods/__init__.py | 8 +- hail/python/hail/methods/impex.py | 140 +--- hail/python/hail/methods/qc.py | 4 +- hail/python/hail/vds/combiner/combine.py | 469 ++++++++++- .../vds/combiner/variant_dataset_combiner.py | 92 ++- hail/python/hail/vds/methods.py | 2 +- .../hail/experimental/test_vcf_combiner.py | 161 ---- hail/python/test/hail/expr/test_expr.py | 27 +- hail/python/test/hail/methods/test_impex.py | 100 +-- hail/python/test/hail/vds/test_combiner.py | 78 +- hail/python/test/hail/vds/test_vds.py | 31 - hail/src/main/scala/is/hail/HailContext.scala | 18 - .../scala/is/hail/asm4s/CodeBuilder.scala | 4 + .../is/hail/backend/spark/SparkBackend.scala | 43 - .../main/scala/is/hail/expr/ir/Binds.scala | 10 + .../main/scala/is/hail/expr/ir/Children.scala | 2 + .../src/main/scala/is/hail/expr/ir/Copy.scala | 4 + .../is/hail/expr/ir/EmitCodeBuilder.scala | 2 - .../main/scala/is/hail/expr/ir/Exists.scala | 2 +- .../scala/is/hail/expr/ir/GenericLines.scala | 4 +- hail/src/main/scala/is/hail/expr/ir/IR.scala | 26 + .../scala/is/hail/expr/ir/InferType.scala | 2 + .../scala/is/hail/expr/ir/Interpretable.scala | 1 + .../main/scala/is/hail/expr/ir/MatrixIR.scala | 2 +- .../scala/is/hail/expr/ir/NestingDepth.scala | 7 + .../is/hail/expr/ir/NormalizeNames.scala | 9 + .../main/scala/is/hail/expr/ir/Parser.scala | 17 +- .../main/scala/is/hail/expr/ir/Pretty.scala | 2 + .../is/hail/expr/ir/PruneDeadFields.scala | 21 + .../scala/is/hail/expr/ir/Requiredness.scala | 27 + .../scala/is/hail/expr/ir/TypeCheck.scala | 6 + .../expr/ir/functions/UtilFunctions.scala | 37 +- .../is/hail/expr/ir/streams/EmitStream.scala | 237 +++++- .../main/scala/is/hail/io/vcf/LoadVCF.scala | 476 ++++++----- .../is/hail/io/vcf/TabixReadVCFIterator.scala | 115 +++ .../test/scala/is/hail/expr/ir/IRSuite.scala | 13 - 55 files changed, 1707 insertions(+), 1890 deletions(-) delete mode 100644 hail/python/cluster-tests/cluster-read-vcfs-check.py delete mode 100644 hail/python/hail/docs/experimental/vcf_combiner.rst rename hail/python/hail/experimental/{vcf_combiner => sparse_mt}/__init__.py (56%) rename hail/python/hail/experimental/{vcf_combiner => sparse_mt}/densify.py (100%) rename hail/python/hail/experimental/{vcf_combiner => sparse_mt}/sparse_split_multi.py (100%) delete mode 100644 hail/python/hail/experimental/vcf_combiner/__main__.py delete mode 100644 hail/python/hail/experimental/vcf_combiner/vcf_combiner.py delete mode 100644 hail/python/test/hail/experimental/test_vcf_combiner.py create mode 100644 hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala diff --git a/hail/python/cluster-tests/cluster-read-vcfs-check.py b/hail/python/cluster-tests/cluster-read-vcfs-check.py deleted file mode 100644 index e4ce72b8af4..00000000000 --- a/hail/python/cluster-tests/cluster-read-vcfs-check.py +++ /dev/null @@ -1,23 +0,0 @@ -import hail as hl - -gvcfs = ['gs://hail-common/test-resources/HG00096.g.vcf.gz', - 'gs://hail-common/test-resources/HG00268.g.vcf.gz'] -hl.init(default_reference='GRCh38') -parts_json = [ - {'start': {'locus': {'contig': 'chr20', 'position': 17821257}}, - 'end': {'locus': {'contig': 'chr20', 'position': 18708366}}, - 'includeStart': True, - 'includeEnd': True}, - {'start': {'locus': {'contig': 'chr20', 'position': 18708367}}, - 'end': {'locus': {'contig': 'chr20', 'position': 19776611}}, - 'includeStart': True, - 'includeEnd': True}, - {'start': {'locus': {'contig': 'chr20', 'position': 19776612}}, - 'end': {'locus': {'contig': 'chr20', 'position': 21144633}}, - 'includeStart': True, - 'includeEnd': True}, -] - -parts = hl.tarray(hl.tinterval(hl.tstruct(locus=hl.tlocus('GRCh38'))))._convert_from_json(parts_json) -for mt in hl.import_gvcfs(gvcfs, parts): - mt._force_count_rows() diff --git a/hail/python/hail/docs/experimental/index.rst b/hail/python/hail/docs/experimental/index.rst index 0e81f0268b4..fb220c3266b 100644 --- a/hail/python/hail/docs/experimental/index.rst +++ b/hail/python/hail/docs/experimental/index.rst @@ -12,7 +12,6 @@ on this page. .. toctree:: :maxdepth: 1 - vcf_combiner ldscsim Contribution Guidelines diff --git a/hail/python/hail/docs/experimental/vcf_combiner.rst b/hail/python/hail/docs/experimental/vcf_combiner.rst deleted file mode 100644 index eef29327fed..00000000000 --- a/hail/python/hail/docs/experimental/vcf_combiner.rst +++ /dev/null @@ -1,220 +0,0 @@ -VCF Combiner -============ - -.. warning:: - - The Hail GVCF combiner is deprecated in favor of the :class:`.VariantDatasetCombiner`. - -Hail has functionality for combining single-sample GVCFs into a multi-sample -matrix table. This process is sometimes called "joint calling", although the -implementation in Hail does not use cohort-level information to reassign individual -genotype calls. - -The resulting matrix table is different from a matrix table imported from a project VCF; -see below for a synopsis of how to use this object. - -Running the Hail GVCF combiner ------------------------------- - -The :func:`.run_combiner` function is the primary entry point to running the Hail GVCF -combiner. A typical script for running the combiner on Google Cloud Dataproc using -``hailctl dataproc`` might look like the below:: - - - import hail as hl - hl.init(log='/home/hail/combiner.log') - - path_to_input_list = 'gs://path/to/input_files.txt' # a file with one GVCF path per line - - inputs = [] - with hl.hadoop_open(path_to_input_list, 'r') as f: - for line in f: - inputs.append(line.strip()) - - output_file = 'gs://path/to/combined/output.mt' # output destination - temp_bucket = 'gs://my-temp-bucket' # bucket for storing intermediate files - hl.experimental.run_combiner(inputs, out_file=output_file, tmp_path=temp_bucket, reference_genome='GRCh38') - - -A command-line tool is also provided as a convenient wrapper around this function. This -tool can be run using the below syntax:: - - python3 -m hail.experimental.vcf_combiner SAMPLE_MAP OUT_FILE TMP_PATH [OPTIONAL ARGS...] - -The below command is equivalent to the Python pipeline above:: - - python3 -m hail.experimental.vcf_combiner \ - gs://path/to/input_files.txt \ - gs://path/to/combined/output.mt \ - gs://my-temp-bucket \ - --reference-genome GRCh38 \ - --log /home/hail/combiner.log - -Pipeline structure -^^^^^^^^^^^^^^^^^^ - -The Hail GVCF combiner merges GVCFs hierarchically, parameterized by the `branch_factor` -setting. The number of rounds of merges is defined as ``math.ceil(math.log(N_GVCFS, BRANCH_FACTOR))``. -With the default branch factor of 100, merging between 101 and 10,000 inputs uses 2 rounds, -and merging between 10,001 and 1,000,000 inputs requires 3 rounds. - -The combiner will print the execution plan before it runs: :: - - 2020-04-01 08:37:32 Hail: INFO: GVCF combiner plan: - Branch factor: 4 - Batch size: 4 - Combining 50 input files in 3 phases with 6 total jobs. - Phase 1: 4 jobs corresponding to 13 intermediate output files. - Phase 2: 1 job corresponding to 4 intermediate output files. - Phase 3: 1 job corresponding to 1 final output file. - - -Pain points -^^^^^^^^^^^ - -The combiner can take some time on large numbers of GVCFs. This time is split -between single-machine planning and compilation work that happens only on the -driver machine, and jobs that take advantage of the entire cluster. For this -reason, its is recommended that clusters with autoscaling functionality are -used, to reduce the overall cost of the pipeline. - -For users running with Google Dataproc, the full documentation for creating -autoscaling policies `can be found here `__. - -A typical YAML policy might look like: :: - - basicAlgorithm: - cooldownPeriod: 120s - yarnConfig: - gracefulDecommissionTimeout: 120s - scaleDownFactor: 1.0 - scaleUpFactor: 1.0 - secondaryWorkerConfig: - maxInstances: MAX_PREEMPTIBLE_INSTANCES - weight: 1 - workerConfig: - maxInstances: 2 - minInstances: 2 - weight: 1 - -For ``MAX_PREEMPTIBLE_INSTANCES``, you should fill in a value based on the number of GVCFs you are merging. -For sample sizes up to about 10,000, a value of 100 should be fine. - -You can start a cluster with this autoscaling policy using ``hailctl``: :: - - hailctl dataproc start cluster_name ...args... --autoscaling-policy=policy_id_or_uri - -Working with sparse matrix tables ---------------------------------- - -Sparse matrix tables are a new method of representing VCF-style data in a space -efficient way. The 'sparse' modifier refers to the fact that these datasets -contain sample-level reference blocks, just like the input GVCFs -- most of the -entries in the matrix are missing, because that entry falls within a reference -block defined at an earlier locus. While unfamiliar, this representation (1) is -incrementally mergeable with other sparse matrix tables, and (2) scales with the -``N_GVCFs``, not ``N_GVCFs^1.5`` as project VCFs do. The schema of a sparse -matrix table also differs from the schema of a dense project VCF imported to -matrix table. They do not have the same ``GT``, ``AD``, and ``PL`` fields found -in a project VCF, but instead have ``LGT``, ``LAD``, ``LPL`` that provide the -same information, but require additional functions to work with in combination -with a sample's local alleles, ``LA``. - -Sample Level Reference Blocks -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -GVCFs represent blocks of homozygous reference calls of similar qualities using -one record. For example: :: - - #CHROM POS ID REF ALT INFO FORMAT SAMPLE_1 - chr1 14523 . C . END=15000 GT:DP:GQ 0/0:19:40 - -This record indicates that sample ``SAMPLE_1`` is homozygous reference until -position 15,000 with approximate ``GQ`` of 40 across the ~500-base-pair. In -short read sequencing, two adjacent loci in a sample's genome will be covered by -mostly the same reads so the quality information about these two loci is highly -correlated; reference blocks explicitly represent regions of reference alleles -with similar quality information. - -A sparse matrix table has an entry field ``END`` that corresponds to the GVCF -``INFO`` field, ``END``. It has the same meaning, but only for the single column -where the END resides. In a sparse matrix table, there will be no defined -entries for this sample between ``chr1:14524`` and ``chr1:15000``, inclusive. - -Local Alleles -^^^^^^^^^^^^^ - -The ``LA`` field constitutes a record's **local alleles**, or the alleles that -appeared in the original GVCF for that sample. ``LA`` is used to interpret the -values of ``LGT`` (local genotype), ``LAD`` (local allele depth), and ``LPL`` -(local phred-scaled genotype likelihoods). This is best explained through -example: :: - - Variant Information - ------------------- - locus: chr22:10678889 - alleles: ["CAT", "C", "TAT"] - - Sample1 (reference block, CAT/CAT) - ------------------------- - DP: 8 - GQ: 21 - LA: [0] - LGT: 0/0 - LAD: NA - LPL: NA - END: 10678898 - - equivalent GT: 0/0 - equivalent AD: [8, 0, 0] - equivalent PL: [0, 21, 42*, 21, 42*, 42*] - - Sample1 (called CAT/TAT) - ------------------------- - DP: 9 - GQ: 77 - LA: [0, 2] - LGT: 0/1 - LAD: [3, 6] - LPL: [137, 0, 77] - END: NA - - equivalent GT: 0/2 - equivalent AD: [3, 0, 6] - equivalent PL: [137, 137*, 137*, 0, 137*, 77] - -The ``LA`` field for the first sample only includes the reference allele (0), -since this locus was the beginning of a reference block in the original GVCF. In -a reference block, LA will typically be an array with only one value, ``0``. The -``LA`` field for the second sample, which contains a variant allele, includes -the reference and that allele (0 and 2, respectively). PL entries above marked -with an asterisk refer to genotypes with alleles not observed in the original -GVCF; the actual value produced by a tool like GATK will be large (a -low-likelihood value), but not exactly the above. As with standard ``GT`` -fields, it is possible to use :meth:`.CallExpression.unphased_diploid_gt_index` -to compute the ``LGT``'s corresponding index into the ``LPL`` array. - - -Functions -~~~~~~~~~ - -There are a number of functions for working with sparse data. Of particular -importance is :func:`~.densify`, which transforms a sparse matrix table to a dense -project-VCF-like matrix table on the fly. While computationally expensive, this -operation is necessary for many downstream analyses, and should be thought of as -roughly costing as much as reading a matrix table created by importing a dense -project VCF. - -.. currentmodule:: hail.experimental - -.. autosummary:: - - run_combiner - densify - sparse_split_multi - lgt_to_gt - -.. autofunction:: run_combiner -.. autofunction:: densify -.. autofunction:: sparse_split_multi -.. autofunction:: lgt_to_gt diff --git a/hail/python/hail/docs/methods/impex.rst b/hail/python/hail/docs/methods/impex.rst index 8ee2cf5cc94..31ccd9aa966 100644 --- a/hail/python/hail/docs/methods/impex.rst +++ b/hail/python/hail/docs/methods/impex.rst @@ -73,7 +73,6 @@ Hail has several functions to import genetics-specific file formats into Hail import_gen import_fam import_locus_intervals - import_gvcfs Export ------ @@ -124,7 +123,6 @@ Reference documentation .. autofunction:: import_table .. autofunction:: import_lines .. autofunction:: import_vcf -.. autofunction:: import_gvcfs .. autofunction:: export_vcf .. autofunction:: export_elasticsearch .. autofunction:: export_bgen diff --git a/hail/python/hail/docs/methods/index.rst b/hail/python/hail/docs/methods/index.rst index 62c496a8ee6..706e264574b 100644 --- a/hail/python/hail/docs/methods/index.rst +++ b/hail/python/hail/docs/methods/index.rst @@ -31,7 +31,6 @@ Methods import_plink import_table import_vcf - import_gvcfs index_bgen read_matrix_table read_table diff --git a/hail/python/hail/experimental/__init__.py b/hail/python/hail/experimental/__init__.py index 6e5767f71e6..d7623a886d8 100644 --- a/hail/python/hail/experimental/__init__.py +++ b/hail/python/hail/experimental/__init__.py @@ -10,7 +10,7 @@ from .import_gtf import import_gtf, get_gene_intervals from .write_multiple import write_matrix_tables, block_matrices_tofiles, export_block_matrices, write_block_matrices from .export_entries_by_col import export_entries_by_col -from .vcf_combiner import sparse_split_multi, run_combiner, lgt_to_gt, densify +from .sparse_mt import sparse_split_multi, densify from .function import define_function from .ldscsim import simulate_phenotypes from .full_outer_join_mt import full_outer_join_mt @@ -53,8 +53,6 @@ 'decode', 'compile_comparison_binary', 'compiled_compare', - 'lgt_to_gt', - 'run_combiner', 'sparse_split_multi', 'densify', 'loop', diff --git a/hail/python/hail/experimental/vcf_combiner/__init__.py b/hail/python/hail/experimental/sparse_mt/__init__.py similarity index 56% rename from hail/python/hail/experimental/vcf_combiner/__init__.py rename to hail/python/hail/experimental/sparse_mt/__init__.py index 6a9ebe811fa..809103319a7 100644 --- a/hail/python/hail/experimental/vcf_combiner/__init__.py +++ b/hail/python/hail/experimental/sparse_mt/__init__.py @@ -1,11 +1,7 @@ -from .vcf_combiner import run_combiner from .sparse_split_multi import sparse_split_multi -from ...vds import lgt_to_gt from .densify import densify __all__ = [ - 'run_combiner', 'sparse_split_multi', - 'lgt_to_gt', 'densify', ] diff --git a/hail/python/hail/experimental/vcf_combiner/densify.py b/hail/python/hail/experimental/sparse_mt/densify.py similarity index 100% rename from hail/python/hail/experimental/vcf_combiner/densify.py rename to hail/python/hail/experimental/sparse_mt/densify.py diff --git a/hail/python/hail/experimental/vcf_combiner/sparse_split_multi.py b/hail/python/hail/experimental/sparse_mt/sparse_split_multi.py similarity index 100% rename from hail/python/hail/experimental/vcf_combiner/sparse_split_multi.py rename to hail/python/hail/experimental/sparse_mt/sparse_split_multi.py diff --git a/hail/python/hail/experimental/vcf_combiner/__main__.py b/hail/python/hail/experimental/vcf_combiner/__main__.py deleted file mode 100644 index 150ca7fb9dc..00000000000 --- a/hail/python/hail/experimental/vcf_combiner/__main__.py +++ /dev/null @@ -1,62 +0,0 @@ -import argparse - -import hail as hl -from .vcf_combiner import CombinerConfig, run_combiner, parse_sample_mapping - - -def main(): - parser = argparse.ArgumentParser(description="Driver for Hail's GVCF combiner", - formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument('sample_map', - help='Path to the sample map, a tab-separated file with two columns. ' - 'The first column is the sample ID, and the second column ' - 'is the GVCF path.') - parser.add_argument('out_file', help='Path to final combiner output.') - parser.add_argument('tmp_path', help='Path to folder for intermediate output ' - '(should be an object store path, if running on the cloud).') - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('--genomes', '-G', action='store_true', - help='Indicates that the combiner is operating on genomes. ' - 'Affects how the genome is partitioned on input.') - group.add_argument('--exomes', '-E', action='store_true', - help='Indicates that the combiner is operating on exomes. ' - 'Affects how the genome is partitioned on input.') - group.add_argument('--import-interval-size', type=int, - help='Interval size for partitioning the reference genome for GVCF import.') - parser.add_argument('--log', help='Hail log path.') - parser.add_argument('--header', - help='External header, must be readable by all executors. ' - 'WARNING: if this option is used, the sample names in the ' - 'GVCFs will be overridden by the names in sample map.', - required=False) - parser.add_argument('--branch-factor', type=int, default=CombinerConfig.default_branch_factor, help='Branch factor.') - parser.add_argument('--batch-size', type=int, default=CombinerConfig.default_phase1_batch_size, help='Batch size.') - parser.add_argument('--target-records', type=int, default=CombinerConfig.default_target_records, help='Target records per partition.') - parser.add_argument('--overwrite', help='overwrite the output path', action='store_true') - parser.add_argument('--key-by-locus-and-alleles', help='Key by both locus and alleles in the final output.', action='store_true') - parser.add_argument('--reference-genome', default='GRCh38', help='Reference genome.') - args = parser.parse_args() - hl.init(log=args.log) - - if not args.overwrite and hl.utils.hadoop_exists(args.out_file): - raise FileExistsError(f"path '{args.out_file}' already exists, use --overwrite to overwrite this path") - - sample_names, sample_paths = parse_sample_mapping(args.sample_map) - run_combiner(sample_paths, - args.out_file, - args.tmp_path, - header=args.header, - sample_names=sample_names, - batch_size=args.batch_size, - branch_factor=args.branch_factor, - target_records=args.target_records, - import_interval_size=args.import_interval_size, - use_genome_default_intervals=args.genomes, - use_exome_default_intervals=args.exomes, - overwrite=args.overwrite, - reference_genome=args.reference_genome, - key_by_locus_and_alleles=args.key_by_locus_and_alleles) - - -if __name__ == '__main__': - main() diff --git a/hail/python/hail/experimental/vcf_combiner/vcf_combiner.py b/hail/python/hail/experimental/vcf_combiner/vcf_combiner.py deleted file mode 100644 index 94ab37a2010..00000000000 --- a/hail/python/hail/experimental/vcf_combiner/vcf_combiner.py +++ /dev/null @@ -1,744 +0,0 @@ -"""An experimental library for combining (g)VCFS into sparse matrix tables""" -# these are necessary for the diver script included at the end of this file -import math -import os -import uuid -from typing import Optional, List, Tuple, Dict - -import hail as hl -from hail import MatrixTable, Table -from hail.experimental.function import Function -from hail.expr import StructExpression -from hail.expr.expressions import expr_bool, expr_str -from hail.genetics.reference_genome import reference_genome_type -from hail.ir import Apply, TableMapRows, MatrixKeyRowsBy -from hail.typecheck import oneof, sequenceof, typecheck -from hail.utils.java import info, warning, Env - -_transform_rows_function_map: Dict[Tuple[hl.HailType], Function] = {} -_merge_function_map: Dict[Tuple[hl.HailType, hl.HailType], Function] = {} - - -@typecheck(string=expr_str, has_non_ref=expr_bool) -def parse_as_ints(string, has_non_ref): - ints = string.split(r'\|') - ints = hl.if_else(has_non_ref, ints[:-1], ints) - return ints.map(lambda i: hl.if_else((hl.len(i) == 0) | (i == '.'), hl.missing(hl.tint32), hl.int32(i))) - - -@typecheck(string=expr_str, has_non_ref=expr_bool) -def parse_as_doubles(string, has_non_ref): - ints = string.split(r'\|') - ints = hl.if_else(has_non_ref, ints[:-1], ints) - return ints.map(lambda i: hl.if_else((hl.len(i) == 0) | (i == '.'), hl.missing(hl.tfloat64), hl.float64(i))) - - -@typecheck(string=expr_str, has_non_ref=expr_bool) -def parse_as_sb_table(string, has_non_ref): - ints = string.split(r'\|') - ints = hl.if_else(has_non_ref, ints[:-1], ints) - return ints.map(lambda xs: xs.split(",").map(hl.int32)) - - -@typecheck(string=expr_str, has_non_ref=expr_bool) -def parse_as_ranksum(string, has_non_ref): - typ = hl.ttuple(hl.tfloat64, hl.tint32) - items = string.split(r'\|') - items = hl.if_else(has_non_ref, items[:-1], items) - return items.map(lambda s: hl.if_else( - (hl.len(s) == 0) | (s == '.'), - hl.missing(typ), - hl.rbind(s.split(','), lambda ss: hl.if_else( - hl.len(ss) != 2, # bad field, possibly 'NaN', just set it null - hl.missing(hl.ttuple(hl.tfloat64, hl.tint32)), - hl.tuple([hl.float64(ss[0]), hl.int32(ss[1])]))))) - - -_as_function_map = { - 'AS_QUALapprox': parse_as_ints, - 'AS_RAW_MQ': parse_as_doubles, - 'AS_RAW_MQRankSum': parse_as_ranksum, - 'AS_RAW_ReadPosRankSum': parse_as_ranksum, - 'AS_SB_TABLE': parse_as_sb_table, - 'AS_VarDP': parse_as_ints, -} - - -def parse_as_fields(info, has_non_ref): - return hl.struct(**{f: info[f] if f not in _as_function_map - else _as_function_map[f](info[f], has_non_ref) for f in info}) - - -def localize(mt): - if isinstance(mt, MatrixTable): - return mt._localize_entries('__entries', '__cols') - return mt - - -def unlocalize(mt): - if isinstance(mt, Table): - return mt._unlocalize_entries('__entries', '__cols', ['s']) - return mt - - -@typecheck(mt=oneof(Table, MatrixTable), info_to_keep=sequenceof(str)) -def transform_gvcf(mt, info_to_keep=[]) -> Table: - """Transforms a gvcf into a sparse matrix table - - The input to this should be some result of either :func:`.import_vcf` or - :func:`.import_gvcfs` with ``array_elements_required=False``. - - There is an assumption that this function will be called on a matrix table - with one column (or a localized table version of the same). - - Parameters - ---------- - mt : :obj:`Union[Table, MatrixTable]` - The gvcf being transformed, if it is a table, then it must be a localized matrix table with - the entries array named ``__entries`` - info_to_keep : :obj:`List[str]` - Any ``INFO`` fields in the gvcf that are to be kept and put in the ``gvcf_info`` entry - field. By default, all ``INFO`` fields except ``END`` and ``DP`` are kept. - - Returns - ------- - :obj:`.Table` - A localized matrix table that can be used as part of the input to `combine_gvcfs`. - - Notes - ----- - This function will parse the following allele specific annotations from - pipe delimited strings into proper values. :: - - AS_QUALapprox - AS_RAW_MQ - AS_RAW_MQRankSum - AS_RAW_ReadPosRankSum - AS_SB_TABLE - AS_VarDP - - """ - if not info_to_keep: - info_to_keep = [name for name in mt.info if name not in ['END', 'DP']] - mt = localize(mt) - - transform_row = _transform_rows_function_map.get(mt.row.dtype) - if transform_row is None or not hl.current_backend()._is_registered_ir_function_name(transform_row._name): - def get_lgt(e, n_alleles, has_non_ref, row): - index = e.GT.unphased_diploid_gt_index() - n_no_nonref = n_alleles - hl.int(has_non_ref) - triangle_without_nonref = hl.triangle(n_no_nonref) - return (hl.case() - .when(e.GT.is_haploid(), - hl.or_missing(e.GT[0] < n_no_nonref, e.GT)) - .when(index < triangle_without_nonref, e.GT) - .when(index < hl.triangle(n_alleles), hl.missing('call')) - .or_error('invalid GT ' + hl.str(e.GT) + ' at site ' + hl.str(row.locus))) - - def make_entry_struct(e, alleles_len, has_non_ref, row): - handled_fields = dict() - handled_names = {'LA', 'gvcf_info', - 'END', - 'LAD', 'AD', - 'LGT', 'GT', - 'LPL', 'PL', - 'LPGT', 'PGT'} - - if 'END' not in row.info: - raise hl.utils.FatalError("the Hail GVCF combiner expects GVCFs to have an 'END' field in INFO.") - if 'GT' not in e: - raise hl.utils.FatalError("the Hail GVCF combiner expects GVCFs to have a 'GT' field in FORMAT.") - - handled_fields['LA'] = hl.range(0, alleles_len - hl.if_else(has_non_ref, 1, 0)) - handled_fields['LGT'] = get_lgt(e, alleles_len, has_non_ref, row) - if 'AD' in e: - handled_fields['LAD'] = hl.if_else(has_non_ref, e.AD[:-1], e.AD) - if 'PGT' in e: - handled_fields['LPGT'] = e.PGT - if 'PL' in e: - handled_fields['LPL'] = hl.if_else(has_non_ref, - hl.if_else(alleles_len > 2, - e.PL[:-alleles_len], - hl.missing(e.PL.dtype)), - hl.if_else(alleles_len > 1, - e.PL, - hl.missing(e.PL.dtype))) - handled_fields['RGQ'] = hl.if_else( - has_non_ref, - hl.if_else(e.GT.is_haploid(), - e.PL[alleles_len - 1], - e.PL[hl.call(0, alleles_len - 1).unphased_diploid_gt_index()]), - hl.missing(e.PL.dtype.element_type)) - - handled_fields['END'] = row.info.END - handled_fields['gvcf_info'] = (hl.case() - .when(hl.is_missing(row.info.END), - hl.struct(**( - parse_as_fields( - row.info.select(*info_to_keep), - has_non_ref) - ))) - .or_missing()) - - pass_through_fields = {k: v for k, v in e.items() if k not in handled_names} - return hl.struct(**handled_fields, **pass_through_fields) - - transform_row = hl.experimental.define_function( - lambda row: hl.rbind( - hl.len(row.alleles), '' == row.alleles[-1], - lambda alleles_len, has_non_ref: hl.struct( - locus=row.locus, - alleles=hl.if_else(has_non_ref, row.alleles[:-1], row.alleles), - rsid=row.rsid, - __entries=row.__entries.map( - lambda e: make_entry_struct(e, alleles_len, has_non_ref, row)))), - mt.row.dtype) - _transform_rows_function_map[mt.row.dtype] = transform_row - return Table(TableMapRows(mt._tir, Apply(transform_row._name, transform_row._ret_type, mt.row._ir))) - - -def transform_one(mt, info_to_keep=[]) -> Table: - return transform_gvcf(mt, info_to_keep) - - -def merge_alleles(alleles): - from hail.expr.functions import _num_allele_type, _allele_ints - return hl.rbind( - alleles.map(lambda a: hl.or_else(a[0], '')) - .fold(lambda s, t: hl.if_else(hl.len(s) > hl.len(t), s, t), ''), - lambda ref: - hl.rbind( - alleles.map( - lambda al: hl.rbind( - al[0], - lambda r: - hl.array([ref]).extend( - al[1:].map( - lambda a: - hl.rbind( - _num_allele_type(r, a), - lambda at: - hl.if_else( - (_allele_ints['SNP'] == at) - | (_allele_ints['Insertion'] == at) - | (_allele_ints['Deletion'] == at) - | (_allele_ints['MNP'] == at) - | (_allele_ints['Complex'] == at), - a + ref[hl.len(r):], - a)))))), - lambda lal: - hl.struct( - globl=hl.array([ref]).extend(hl.array(hl.set(hl.flatten(lal)).remove(ref))), - local=lal))) - - -def combine(ts): - def renumber_entry(entry, old_to_new) -> StructExpression: - # global index of alternate (non-ref) alleles - return entry.annotate(LA=entry.LA.map(lambda lak: old_to_new[lak])) - - merge_function = _merge_function_map.get((ts.row.dtype, ts.globals.dtype)) - if merge_function is None or not hl.current_backend()._is_registered_ir_function_name(merge_function._name): - merge_function = hl.experimental.define_function( - lambda row, gbl: - hl.rbind( - merge_alleles(row.data.map(lambda d: d.alleles)), - lambda alleles: - hl.struct( - locus=row.locus, - alleles=alleles.globl, - **({'rsid': hl.find(hl.is_defined, row.data.map(lambda d: d.rsid))} if 'rsid' in row.data.dtype.element_type else {}), - __entries=hl.bind( - lambda combined_allele_index: - hl.range(0, hl.len(row.data)).flatmap( - lambda i: - hl.if_else(hl.is_missing(row.data[i].__entries), - hl.range(0, hl.len(gbl.g[i].__cols)) - .map(lambda _: hl.missing(row.data[i].__entries.dtype.element_type)), - hl.bind( - lambda old_to_new: row.data[i].__entries.map( - lambda e: renumber_entry(e, old_to_new)), - hl.range(0, hl.len(alleles.local[i])).map( - lambda j: combined_allele_index[alleles.local[i][j]])))), - hl.dict(hl.range(0, hl.len(alleles.globl)).map( - lambda j: hl.tuple([alleles.globl[j], j])))))), - ts.row.dtype, ts.globals.dtype) - _merge_function_map[(ts.row.dtype, ts.globals.dtype)] = merge_function - ts = Table(TableMapRows(ts._tir, Apply(merge_function._name, - merge_function._ret_type, - ts.row._ir, - ts.globals._ir))) - return ts.transmute_globals(__cols=hl.flatten(ts.g.map(lambda g: g.__cols))) - - -@typecheck(mts=sequenceof(oneof(Table, MatrixTable))) -def combine_gvcfs(mts): - """Merges gvcfs and/or sparse matrix tables - - Parameters - ---------- - mts : :obj:`List[Union[Table, MatrixTable]]` - The matrix tables (or localized versions) to combine - - Returns - ------- - :class:`.MatrixTable` - - Notes - ----- - All of the input tables/matrix tables must have the same partitioning. This - module provides no method of repartitioning data. - """ - ts = hl.Table.multi_way_zip_join([localize(mt) for mt in mts], 'data', 'g') - combined = combine(ts) - return unlocalize(combined) - - -@typecheck(mt=hl.MatrixTable, desired_average_partition_size=int, tmp_path=str) -def calculate_new_intervals(mt, desired_average_partition_size: int, tmp_path: str): - """takes a table, keyed by ['locus', ...] and produces a list of intervals suitable - for repartitioning a combiner matrix table. - - Parameters - ---------- - mt : :class:`.MatrixTable` - Sparse MT intermediate. - desired_average_partition_size : :obj:`int` - Average target number of rows for each partition. - tmp_path : :obj:`str` - Temporary path for scan checkpointing. - - Returns - ------- - (:obj:`List[Interval]`, :obj:`.Type`) - """ - assert list(mt.row_key) == ['locus'] - assert isinstance(mt.locus.dtype, hl.tlocus) - reference_genome = mt.locus.dtype.reference_genome - end = hl.Locus(reference_genome.contigs[-1], - reference_genome.lengths[reference_genome.contigs[-1]], - reference_genome=reference_genome) - - (n_rows, n_cols) = mt.count() - - if n_rows == 0: - raise ValueError('empty table!') - - # split by a weight function that takes into account the number of - # dense entries per row. However, give each row some base weight - # to prevent densify computations from becoming unbalanced (these - # scale roughly linearly with N_ROW * N_COL) - ht = mt.select_rows(weight=hl.agg.count() + (n_cols // 25) + 1).rows().checkpoint(tmp_path) - - total_weight = ht.aggregate(hl.agg.sum(ht.weight)) - partition_weight = int(total_weight / (n_rows / desired_average_partition_size)) - - ht = ht.annotate(cumulative_weight=hl.scan.sum(ht.weight), - last_weight=hl.scan._prev_nonnull(ht.weight), - row_idx=hl.scan.count()) - - def partition_bound(x): - return x - (x % hl.int64(partition_weight)) - - at_partition_bound = partition_bound(ht.cumulative_weight) != partition_bound(ht.cumulative_weight - ht.last_weight) - - ht = ht.filter(at_partition_bound | (ht.row_idx == n_rows - 1)) - ht = ht.annotate(start=hl.or_else( - hl.scan._prev_nonnull(hl.locus_from_global_position(ht.locus.global_position() + 1, - reference_genome=reference_genome)), - hl.locus_from_global_position(0, reference_genome=reference_genome))) - ht = ht.select( - interval=hl.interval(start=hl.struct(locus=ht.start), end=hl.struct(locus=ht.locus), includes_end=True)) - - intervals_dtype = hl.tarray(ht.interval.dtype) - intervals = ht.aggregate(hl.agg.collect(ht.interval)) - last_st = hl.eval( - hl.locus_from_global_position(hl.literal(intervals[-1].end.locus).global_position() + 1, - reference_genome=reference_genome)) - interval = hl.Interval(start=hl.Struct(locus=last_st), end=hl.Struct(locus=end), includes_end=True) - intervals.append(interval) - return intervals, intervals_dtype - - -@typecheck(reference_genome=reference_genome_type, interval_size=int) -def calculate_even_genome_partitioning(reference_genome, interval_size) -> List[hl.utils.Interval]: - """create a list of locus intervals suitable for importing and merging gvcfs. - - Parameters - ---------- - reference_genome: :class:`str` or :class:`.ReferenceGenome`, - Reference genome to use. NOTE: only GRCh37 and GRCh38 references - are supported. - interval_size: :obj:`int` The ceiling and rough target of interval size. - Intervals will never be larger than this, but may be smaller. - - Returns - ------- - :obj:`List[Interval]` - """ - def calc_parts(contig): - def locus_interval(start, end): - return hl.Interval( - start=hl.Locus(contig=contig, position=start, reference_genome=reference_genome), - end=hl.Locus(contig=contig, position=end, reference_genome=reference_genome), - includes_end=True) - - contig_length = reference_genome.lengths[contig] - n_parts = math.ceil(contig_length / interval_size) - real_size = math.ceil(contig_length / n_parts) - n = 1 - intervals = [] - while n < contig_length: - start = n - end = min(n + real_size, contig_length) - intervals.append(locus_interval(start, end)) - n = end + 1 - - return intervals - - if reference_genome.name == 'GRCh37': - contigs = [f'{i}' for i in range(1, 23)] + ['X', 'Y', 'MT'] - elif reference_genome.name == 'GRCh38': - contigs = [f'chr{i}' for i in range(1, 23)] + ['chrX', 'chrY', 'chrM'] - else: - raise ValueError( - f"Unsupported reference genome '{reference_genome.name}', " - "only 'GRCh37' and 'GRCh38' are supported") - - intervals = [] - for ctg in contigs: - intervals.extend(calc_parts(ctg)) - return intervals - - -# END OF VCF COMBINER LIBRARY, BEGINNING OF BEST PRACTICES SCRIPT # - - -class Merge(object): - def __init__(self, - inputs: List[int], - input_total_size: int): - self.inputs: List[int] = inputs - self.input_total_size: int = input_total_size - - -class Job(object): - def __init__(self, merges: List[Merge]): - self.merges: List[Merge] = merges - self.input_total_size = sum(m.input_total_size for m in merges) - - -class Phase(object): - def __init__(self, jobs: List[Job]): - self.jobs: List[Job] = jobs - - -class CombinerPlan(object): - def __init__(self, - file_size: List[List[int]], - phases: List[Phase]): - self.file_size = file_size - self.phases = phases - self.merge_per_phase = len(file_size[0]) - self.total_merge = self.merge_per_phase * len(phases) - - -class CombinerConfig(object): - default_max_partitions_per_job = 75_000 - default_branch_factor = 100 - default_phase1_batch_size = 100 - default_target_records = 30_000 - - # These are used to calculate intervals for reading GVCFs in the combiner - # The genome interval size results in 2568 partions for GRCh38. The exome - # interval size assumes that they are around 2% the size of a genome and - # result in 65 partitions for GRCh38. - default_genome_interval_size = 1_200_000 - default_exome_interval_size = 60_000_000 - - def __init__(self, - branch_factor: int = default_branch_factor, - batch_size: int = default_phase1_batch_size, - target_records: int = default_target_records): - self.branch_factor: int = branch_factor - self.batch_size: int = batch_size - self.target_records: int = target_records - - @classmethod - def default(cls) -> 'CombinerConfig': - return CombinerConfig() - - def plan(self, n_inputs: int) -> CombinerPlan: - assert n_inputs > 0 - - def int_ceil(x): - return int(math.ceil(x)) - - tree_height = int_ceil(math.log(n_inputs, self.branch_factor)) - phases: List[Phase] = [] - file_size: List[List[int]] = [] # List of file size per phase - - file_size.append([1 for _ in range(n_inputs)]) - while len(file_size[-1]) > 1: - batch_size_this_phase = self.batch_size if len(file_size) == 1 else 1 - last_stage_files = file_size[-1] - n = len(last_stage_files) - i = 0 - jobs = [] - while (i < n): - job = [] - job_i = 0 - while job_i < batch_size_this_phase and i < n: - merge = [] - merge_i = 0 - merge_size = 0 - while merge_i < self.branch_factor and i < n: - merge_size += last_stage_files[i] - merge.append(i) - merge_i += 1 - i += 1 - job.append(Merge(merge, merge_size)) - job_i += 1 - jobs.append(Job(job)) - file_size.append([merge.input_total_size for job in jobs for merge in job.merges]) - phases.append(Phase(jobs)) - - assert len(phases) == tree_height - for layer in file_size: - assert sum(layer) == n_inputs - - phase_strs = [] - total_jobs = 0 - for i, phase in enumerate(phases): - n = len(phase.jobs) - job_str = hl.utils.misc.plural('job', n) - n_files_produced = len(file_size[i + 1]) - adjective = 'final' if n_files_produced == 1 else 'intermediate' - file_str = hl.utils.misc.plural('file', n_files_produced) - phase_strs.append( - f'\n Phase {i + 1}: {n} {job_str} corresponding to {n_files_produced} {adjective} output {file_str}.') - total_jobs += n - - info(f"GVCF combiner plan:\n" - f" Branch factor: {self.branch_factor}\n" - f" Phase 1 batch size: {self.batch_size}\n" - f" Combining {n_inputs} input files in {tree_height} phases with {total_jobs} total jobs.{''.join(phase_strs)}\n") - return CombinerPlan(file_size, phases) - - -def run_combiner(sample_paths: List[str], - out_file: str, - tmp_path: str, - *, - intervals: Optional[List[hl.utils.Interval]] = None, - import_interval_size: Optional[int] = None, - use_genome_default_intervals: bool = False, - use_exome_default_intervals: bool = False, - header: Optional[str] = None, - sample_names: Optional[List[str]] = None, - branch_factor: int = CombinerConfig.default_branch_factor, - batch_size: int = CombinerConfig.default_phase1_batch_size, - target_records: int = CombinerConfig.default_target_records, - overwrite: bool = False, - reference_genome: str = 'default', - contig_recoding: Optional[Dict[str, str]] = None, - key_by_locus_and_alleles: bool = False): - """Run the Hail VCF combiner, performing a hierarchical merge to create a combined sparse matrix table. - - **Partitioning** - - The partitioning of input GVCFs, which determines the maximum parallelism per file, - is determined the four parameters below. One of these parameters must be passed to - this function. - - - `intervals` -- User-supplied intervals. - - `import_interval_size` -- Use intervals of this uniform size across the genome. - - `use_genome_default_intervals` -- Use intervals of typical uniform size for whole - genome GVCFs. - - `use_exome_default_intervals` -- Use intervals of typical uniform size for exome - GVCFs. - - It is recommended that new users include either `use_genome_default_intervals` or - `use_exome_default_intervals`. - - Note also that the partitioning of the final, combined matrix table does not depend - the GVCF input partitioning. - - Parameters - ---------- - sample_paths : :obj:`list` of :class:`str` - Paths to individual GVCFs. - out_file : :class:`str` - Path to final combined matrix table. - tmp_path : :class:`str` - Path for intermediate output. - intervals : list of :class:`.Interval` or None - Import GVCFs with specified partition intervals. - import_interval_size : :obj:`int` or None - Import GVCFs with uniform partition intervals of specified size. - use_genome_default_intervals : :obj:`bool` - Import GVCFs with uniform partition intervals of default size for - whole-genome data. - use_exome_default_intervals : :obj:`bool` - Import GVCFs with uniform partition intervals of default size for - exome data. - header : :class:`str` or None - External header file to use as GVCF header for all inputs. If defined, `sample_names` must be defined as well. - sample_names: list of :class:`str` or None - Sample names, to be used with `header`. - branch_factor : :obj:`int` - Combiner branch factor. - batch_size : :obj:`int` - Combiner batch size. - target_records : :obj:`int` - Target records per partition in each combiner phase after the first. - overwrite : :obj:`bool` - Overwrite output file, if it exists. - reference_genome : :class:`str` - Reference genome for GVCF import. - contig_recoding: :obj:`dict` of (:class:`str`, :obj:`str`), optional - Mapping from contig name in gVCFs to contig name the reference - genome. All contigs must be present in the - `reference_genome`, so this is useful for mapping - differently-formatted data onto known references. - key_by_locus_and_alleles : :obj:`bool` - Key by both locus and alleles in the final output. - - Returns - ------- - None - - """ - hl.utils.no_service_backend('vcf_combiner') - flagname = 'no_ir_logging' - prev_flag_value = hl._get_flags(flagname).get(flagname) - hl._set_flags(**{flagname: '1'}) - tmp_path += f'/combiner-temporary/{uuid.uuid4()}/' - if header is not None: - assert sample_names is not None - assert len(sample_names) == len(sample_paths) - - n_partition_args = (int(intervals is not None) - + int(import_interval_size is not None) - + int(use_genome_default_intervals) - + int(use_exome_default_intervals)) - - if n_partition_args == 0: - raise ValueError("'run_combiner': require one argument from 'intervals', 'import_interval_size', " - "'use_genome_default_intervals', or 'use_exome_default_intervals' to choose GVCF partitioning") - if n_partition_args > 1: - warning("'run_combiner': multiple colliding arguments found from 'intervals', 'import_interval_size', " - "'use_genome_default_intervals', or 'use_exome_default_intervals'." - "\n The argument found first in the list in this warning will be used, and others ignored.") - - if intervals is not None: - info(f"Using {len(intervals)} user-supplied intervals as partitioning for GVCF import") - elif import_interval_size is not None: - intervals = calculate_even_genome_partitioning(reference_genome, import_interval_size) - info(f"Using {len(intervals)} intervals with user-supplied size" - f" {import_interval_size} as partitioning for GVCF import") - elif use_genome_default_intervals: - size = CombinerConfig.default_genome_interval_size - intervals = calculate_even_genome_partitioning(reference_genome, size) - info(f"Using {len(intervals)} intervals with default whole-genome size" - f" {size} as partitioning for GVCF import") - elif use_exome_default_intervals: - size = CombinerConfig.default_exome_interval_size - intervals = calculate_even_genome_partitioning(reference_genome, size) - info(f"Using {len(intervals)} intervals with default exome size" - f" {size} as partitioning for GVCF import") - - assert intervals is not None - - config = CombinerConfig(branch_factor=branch_factor, - batch_size=batch_size, - target_records=target_records) - plan = config.plan(len(sample_paths)) - - files_to_merge = sample_paths - n_phases = len(plan.phases) - total_ops = len(files_to_merge) * n_phases - total_work_done = 0 - for phase_i, phase in enumerate(plan.phases): - phase_i += 1 # used for info messages, 1-indexed for readability - - n_jobs = len(phase.jobs) - merge_str = 'input GVCFs' if phase_i == 1 else 'intermediate sparse matrix tables' - job_str = hl.utils.misc.plural('job', n_jobs) - info(f"Starting phase {phase_i}/{n_phases}, merging {len(files_to_merge)} {merge_str} in {n_jobs} {job_str}.") - - if phase_i > 1: - intervals, intervals_dtype = calculate_new_intervals(hl.read_matrix_table(files_to_merge[0]), - config.target_records, - os.path.join(tmp_path, - f'phase{phase_i}_interval_checkpoint.ht')) - - new_files_to_merge = [] - - for job_i, job in enumerate(phase.jobs): - job_i += 1 # used for info messages, 1-indexed for readability - - n_merges = len(job.merges) - merge_str = hl.utils.misc.plural('file', n_merges) - pct_total = 100 * job.input_total_size / total_ops - info( - f"Starting phase {phase_i}/{n_phases}, job {job_i}/{len(phase.jobs)} to create {n_merges} merged {merge_str}, corresponding to ~{pct_total:.1f}% of total I/O.") - merge_mts: List[MatrixTable] = [] - for merge in job.merges: - inputs = [files_to_merge[i] for i in merge.inputs] - - if phase_i == 1: - mts = [transform_gvcf(vcf) - for vcf in hl.import_gvcfs(inputs, intervals, array_elements_required=False, - _external_header=header, - _external_sample_ids=[[sample_names[i]] for i in - merge.inputs] if header is not None else None, - reference_genome=reference_genome, - contig_recoding=contig_recoding)] - else: - mts = Env.spark_backend("vcf_combiner").read_multiple_matrix_tables(inputs, intervals, - intervals_dtype) - - merge_mts.append(combine_gvcfs(mts)) - - if phase_i == n_phases: # final merge! - assert n_jobs == 1 - assert len(merge_mts) == 1 - [final_mt] = merge_mts - - if key_by_locus_and_alleles: - final_mt = MatrixTable(MatrixKeyRowsBy(final_mt._mir, ['locus', 'alleles'], is_sorted=True)) - final_mt.write(out_file, overwrite=overwrite) - new_files_to_merge = [out_file] - info(f"Finished phase {phase_i}/{n_phases}, job {job_i}/{len(phase.jobs)}, 100% of total I/O finished.") - break - - tmp = f'{tmp_path}_phase{phase_i}_job{job_i}/' - hl.experimental.write_matrix_tables(merge_mts, tmp, overwrite=True) - pad = len(str(len(merge_mts) - 1)) - new_files_to_merge.extend(tmp + str(n).zfill(pad) + '.mt' for n in range(len(merge_mts))) - total_work_done += job.input_total_size - info( - f"Finished {phase_i}/{n_phases}, job {job_i}/{len(phase.jobs)}, {100 * total_work_done / total_ops:.1f}% of total I/O finished.") - - info(f"Finished phase {phase_i}/{n_phases}.") - - files_to_merge = new_files_to_merge - - assert files_to_merge == [out_file] - - info("Finished!") - hl._set_flags(**{flagname: prev_flag_value}) - - -def parse_sample_mapping(sample_map_path: str) -> Tuple[List[str], List[str]]: - sample_names: List[str] = list() - sample_paths: List[str] = list() - - with hl.hadoop_open(sample_map_path) as f: - for line in f: - [name, path] = line.strip().split('\t') - sample_names.append(name) - sample_paths.append(path) - - return sample_names, sample_paths diff --git a/hail/python/hail/expr/__init__.py b/hail/python/hail/expr/__init__.py index dac6e84d6ef..3aa25730828 100644 --- a/hail/python/hail/expr/__init__.py +++ b/hail/python/hail/expr/__init__.py @@ -35,7 +35,7 @@ contig_length, liftover, min_rep, uniroot, format, approx_equal, reversed, bit_and, bit_or, bit_xor, bit_lshift, bit_rshift, bit_not, bit_count, binary_search, logit, expit, _values_similar, _showstr, _sort_by, _compare, _locus_windows_per_contig, shuffle, _console_log, dnorm, dchisq, - query_table, keyed_union, keyed_intersection, repeat) + query_table, keyed_union, keyed_intersection, repeat, _zip_join_producers) __all__ = ['HailType', 'hail_type', @@ -309,5 +309,6 @@ 'query_table', 'keyed_union', 'keyed_intersection', + '_zip_join_producers', 'repeat', ] diff --git a/hail/python/hail/expr/functions.py b/hail/python/hail/expr/functions.py index 4be0cf23130..ffa37438f70 100644 --- a/hail/python/hail/expr/functions.py +++ b/hail/python/hail/expr/functions.py @@ -5058,6 +5058,32 @@ def _union_intersection_base(name, arrays, key, join_f, result_f): return result_f(construct_expr(zj, zj.typ, indices, aggs)) +def _zip_join_producers(contexts, stream_f, key, join_f): + ctx_uid = Env.get_uid() + + ctx_var = construct_variable(ctx_uid, contexts.dtype.element_type) + stream_req = stream_f(ctx_var) + make_prod_ir = stream_req._ir + if isinstance(make_prod_ir.typ, hl.tarray): + make_prod_ir = ir.ToStream(make_prod_ir) + t = stream_req.dtype.element_type + + key_typ = hl.tstruct(**{k: t[k] for k in key}) + vals_typ = hl.tarray(t) + + key_uid = Env.get_uid() + vals_uid = Env.get_uid() + + key_var = construct_variable(key_uid, key_typ) + vals_var = construct_variable(vals_uid, vals_typ) + + join_ir = join_f(key_var, vals_var) + zj = ir.ToArray( + ir.StreamZipJoinProducers(contexts._ir, ctx_uid, make_prod_ir, key, key_uid, vals_uid, join_ir._ir)) + indices, aggs = unify_all(contexts, stream_req, join_ir) + return construct_expr(zj, zj.typ, indices, aggs) + + @typecheck(arrays=expr_oneof(expr_stream(expr_any), expr_array(expr_any)), key=sequenceof(builtins.str)) def keyed_intersection(*arrays, key): """Compute the intersection of sorted arrays on a given key. diff --git a/hail/python/hail/expr/type_parsing.py b/hail/python/hail/expr/type_parsing.py index e0594c2bd65..884f524938b 100644 --- a/hail/python/hail/expr/type_parsing.py +++ b/hail/python/hail/expr/type_parsing.py @@ -153,3 +153,91 @@ def visit_nat_variable(self, node, visited_children): type_node_visitor = TypeConstructor() + +vcf_type_grammar = Grammar( + r""" + type = _ (array / set / int32 / int64 / float32 / float64 / str / bool / call / struct) _ + int64 = "Int64" + int32 = "Int32" + float32 = "Float32" + float64 = "Float64" + bool = "Boolean" + call = "Call" + str = "String" + array = "Array" _ "[" type "]" + set = "Set" _ "[" type "]" + struct = "Struct" _ "{" (fields / _) "}" + fields = field ("," field)* + field = identifier ":" type + identifier = _ (simple_identifier / escaped_identifier) _ + simple_identifier = ~r"\w+" + escaped_identifier = ~"`([^`\\\\]|\\\\.)*`" + _ = ~r"\s*" + """) + + +class VCFTypeConstructor(NodeVisitor): + def generic_visit(self, node, visited_children): + return visited_children + + def visit_type(self, node, visited_children): + _, [t], _ = visited_children + return t + + def visit_int64(self, node, visited_children): + return types.tint64 + + def visit_int32(self, node, visited_children): + return types.tint32 + + def visit_float64(self, node, visited_children): + return types.tfloat64 + + def visit_float32(self, node, visited_children): + return types.tfloat32 + + def visit_bool(self, node, visited_children): + return types.tbool + + def visit_call(self, node, visited_children): + return types.tcall + + def visit_str(self, node, visited_children): + return types.tstr + + def visit_array(self, node, visited_children): + tarray, _, bracket, t, bracket = visited_children + return types.tarray(t) + + def visit_set(self, node, visited_children): + tarray, _, bracket, t, bracket = visited_children + return types.tset(t) + + def visit_struct(self, node, visited_children): + tstruct, _, brace, maybe_fields, brace = visited_children + if not maybe_fields: + return types.tstruct() + else: + fields = maybe_fields[0] + return types.tstruct(**dict(fields)) + + def visit_fields(self, node, visited_children): + first, rest = visited_children + return [first] + [field for comma, field in rest] + + def visit_field(self, node, visited_children): + name, comma, type = visited_children + return (name, type) + + def visit_identifier(self, node, visited_children): + _, [id], _ = visited_children + return id + + def visit_simple_identifier(self, node, visited_children): + return node.text + + def visit_escaped_identifier(self, node, visited_children): + return unescape_parsable(node.text[1:-1]) + + +vcf_type_node_visitor = VCFTypeConstructor() diff --git a/hail/python/hail/ir/__init__.py b/hail/python/hail/ir/__init__.py index 7f593785f3f..f7f66d3cc67 100644 --- a/hail/python/hail/ir/__init__.py +++ b/hail/python/hail/ir/__init__.py @@ -1,6 +1,5 @@ from .export_type import ExportType -from .base_ir import BaseIR, IR, TableIR, MatrixIR, BlockMatrixIR, \ - JIRVectorReference +from .base_ir import BaseIR, IR, TableIR, MatrixIR, BlockMatrixIR from .ir import MatrixWrite, MatrixMultiWrite, BlockMatrixWrite, \ BlockMatrixMultiWrite, TableToValueApply, \ MatrixToValueApply, BlockMatrixToValueApply, BlockMatrixCollect, \ @@ -18,7 +17,8 @@ GetTupleElement, Die, ConsoleLog, Apply, ApplySeeded, RNGStateLiteral, RNGSplit,\ TableCount, TableGetGlobals, TableCollect, TableAggregate, MatrixCount, \ MatrixAggregate, TableWrite, udf, subst, clear_session_functions, ReadPartition, \ - PartitionNativeIntervalReader, StreamMultiMerge, StreamZipJoin, StreamAgg + PartitionNativeIntervalReader, StreamMultiMerge, StreamZipJoin, StreamAgg, StreamZipJoinProducers, \ + GVCFPartitionReader from .register_functions import register_functions from .register_aggregators import register_aggregators from .table_ir import (MatrixRowsTable, TableJoin, TableLeftJoinRightDistinct, TableIntervalJoin, @@ -36,7 +36,7 @@ MatrixRowsHead, MatrixColsHead, MatrixRowsTail, MatrixColsTail, \ MatrixExplodeCols, CastTableToMatrix, MatrixAnnotateRowsTable, \ MatrixAnnotateColsTable, MatrixToMatrixApply, MatrixRename, \ - MatrixFilterIntervals, JavaMatrix, JavaMatrixVectorRef + MatrixFilterIntervals, JavaMatrix from .blockmatrix_ir import BlockMatrixRead, BlockMatrixMap, BlockMatrixMap2, \ BlockMatrixDot, BlockMatrixBroadcast, BlockMatrixAgg, BlockMatrixFilter, \ BlockMatrixDensify, BlockMatrixSparsifier, BandSparsifier, \ @@ -67,7 +67,6 @@ 'TableIR', 'MatrixIR', 'BlockMatrixIR', - 'JIRVectorReference', 'register_functions', 'register_aggregators', 'filter_predicate_with_keep', @@ -173,6 +172,7 @@ 'toStream', 'ToStream', 'StreamZipJoin', + 'StreamZipJoinProducers', 'StreamMultiMerge', 'LowerBoundOnOrderedCollection', 'GroupByKey', @@ -260,7 +260,6 @@ 'MatrixRename', 'MatrixFilterIntervals', 'JavaMatrix', - 'JavaMatrixVectorRef', 'MatrixReader', 'MatrixNativeReader', 'MatrixRangeReader', @@ -320,6 +319,7 @@ 'TableNativeFanoutWriter', 'ReadPartition', 'PartitionNativeIntervalReader', + 'GVCFPartitionReader', 'TableGen', 'Partitioner' ] diff --git a/hail/python/hail/ir/base_ir.py b/hail/python/hail/ir/base_ir.py index 2df2d474550..777e32c1f69 100644 --- a/hail/python/hail/ir/base_ir.py +++ b/hail/python/hail/ir/base_ir.py @@ -1,7 +1,6 @@ import abc from hail.expr.types import tstream -from hail.utils.java import Env from .renderer import Renderer, PlainRenderer, Renderable @@ -533,24 +532,3 @@ def typ(self): def renderable_new_block(self, i: int) -> bool: return True - - -class JIRVectorReference(object): - def __init__(self, jid, length, item_type): - self.jid = jid - self.length = length - self.item_type = item_type - - def __len__(self): - return self.length - - def __del__(self): - # can't do anything if the hail context is stopped - if Env._hc is None: - return - try: - Env.backend()._jhc.pyRemoveIrVector(self.jid) - # there is only so much we can do if the attempt to remove the unused IR fails, - # especially since this will often get called during interpreter shutdown. - except Exception: - pass diff --git a/hail/python/hail/ir/ir.py b/hail/python/hail/ir/ir.py index 347331e1458..b2fa9f51658 100644 --- a/hail/python/hail/ir/ir.py +++ b/hail/python/hail/ir/ir.py @@ -7,7 +7,7 @@ import hail from hail.expr.types import dtype, HailType, hail_type, tint32, tint64, \ tfloat32, tfloat64, tstr, tbool, tarray, tstream, tndarray, tset, tdict, \ - tstruct, ttuple, tinterval, tvoid, trngstate + tstruct, ttuple, tinterval, tvoid, trngstate, tlocus, tcall from hail.ir.blockmatrix_writer import BlockMatrixWriter, BlockMatrixMultiWriter from hail.typecheck import typecheck, typecheck_method, sequenceof, numeric, \ sized_tupleof, nullable, tupleof, anytype, func_spec @@ -1368,6 +1368,70 @@ def _compute_type(self, env, agg_env, deep_typecheck): return tstream(self.a.typ.element_type) +class StreamZipJoinProducers(IR): + @typecheck_method(contexts=IR, + ctx_name=str, + make_producer=IR, + key=sequenceof(str), + cur_key=str, + cur_vals=str, + join_f=IR) + def __init__(self, contexts, ctx_name, make_producer, key, cur_key, cur_vals, join_f): + super().__init__(contexts, make_producer, join_f) + self.contexts = contexts + self.ctx_name = ctx_name + self.make_producer = make_producer + self.key = key + self.cur_key = cur_key + self.cur_vals = cur_vals + self.join_f = join_f + + def _handle_randomness(self, create_uids): + assert not create_uids + return self + + @typecheck_method(new_ir=IR) + def copy(self, *new_irs): + assert len(new_irs) == 3 + return StreamZipJoinProducers(new_irs[0], self.ctx_name, new_irs[1], + self.key, self.cur_key, self.cur_vals, new_irs[2]) + + def head_str(self): + return '({}) {} {} {}'.format(' '.join([escape_id(x) for x in self.key]), self.ctx_name, + self.cur_key, self.cur_vals) + + def _compute_type(self, env, agg_env, deep_typecheck): + self.contexts.compute_type(env, agg_env, deep_typecheck) + ctx_elt_type = self.contexts.typ.element_type + self.make_producer.compute_type({**env, self.ctx_name: ctx_elt_type}, agg_env, deep_typecheck) + stream_t = self.make_producer.typ + struct_t = stream_t.element_type + new_env = {**env} + new_env[self.cur_key] = tstruct(**{k: struct_t[k] for k in self.key}) + new_env[self.cur_vals] = tarray(struct_t) + self.join_f.compute_type(new_env, agg_env, deep_typecheck) + return tstream(self.join_f.typ) + + def renderable_bindings(self, i, default_value=None): + if i == 1: + if default_value is None: + ctx_t = self.contexts.typ.element_type + else: + ctx_t = default_value + return {self.ctx_name: ctx_t} + elif i == 2: + if default_value is None: + struct_t = self.make_producer.typ.element_type + key_x = tstruct(**{k: struct_t[k] for k in self.key}) + vals_x = tarray(struct_t) + else: + key_x = default_value + vals_x = default_value + return {self.cur_key: key_x, self.cur_vals: vals_x} + else: + return {} + + class StreamZipJoin(IR): @typecheck_method(streams=sequenceof(IR), key=sequenceof(str), cur_key=str, cur_vals=str, join_f=IR) def __init__(self, streams, key, cur_key, cur_vals, join_f): @@ -3181,6 +3245,100 @@ def row_type(self): pass +class GVCFPartitionReader(PartitionReader): + + entries_field_name = '__entries' + def __init__(self, header, call_fields, entry_float_type, array_elements_required, rg, contig_recoding, + skip_invalid_loci, filter, find, replace, uid_field): + self.header = header + self.call_fields = call_fields + self.entry_float_type = entry_float_type + self.array_elements_required = array_elements_required + self.rg = rg + self.contig_recoding = contig_recoding + self.skip_invalid_loci = skip_invalid_loci + self.filter = filter + self.find = find + self.replace = replace + self.uid_field = uid_field + + def with_uid_field(self, uid_field): + return GVCFPartitionReader(self.header, + self.call_fields, + self.entry_float_type, + self.array_elements_required, + self.rg, + self.contig_recoding, + self.skip_invalid_loci, + self.filter, + self.find, + self.replace, + uid_field) + + def render(self): + return escape_str(json.dumps({"name": "GVCFPartitionReader", + "header": {"name": "VCFHeaderInfo", **self.header}, + "callFields": list(self.call_fields), + "entryFloatType": "Float64" if self.entry_float_type == tfloat64 else "Float32", + "arrayElementsRequired": self.array_elements_required, + "rg": self.rg.name if self.rg is not None else None, + "contigRecoding": self.contig_recoding, + "filterAndReplace": { + "name": "TextInputFilterAndReplace", + "filter": self.filter, + "find": self.find, + "replace": self.replace, + }, + "skipInvalidLoci": self.skip_invalid_loci, + "entriesFieldName": GVCFPartitionReader.entries_field_name, + "uidFieldName": self.uid_field if self.uid_field is not None else '__dummy'})) + + def _eq(self, other): + return isinstance(other, GVCFPartitionReader) \ + and self.header == other.header \ + and self.call_fields == other.call_fields \ + and self.entry_float_type == other.entry_float_type \ + and self.array_elements_required == other.array_elements_required \ + and self.rg == other.rg \ + and self.contig_recoding == other.contig_recoding \ + and self.skip_invalid_loci == other.skip_invalid_loci \ + and self.filter == other.filter \ + and self.find == other.find \ + and self.replace == other.replace \ + and self.uid_field == other.uid_field + + def row_type(self): + if self.uid_field is not None: + uid_fd = {self.uid_field: ttuple(tint64, tint64)} + else: + uid_fd = {} + + from hail.expr.type_parsing import vcf_type_grammar, vcf_type_node_visitor + + def parse_type(t): + tree = vcf_type_grammar.parse(t) + return vcf_type_node_visitor.visit(tree) + + def subst_format(name, t): + if t == tfloat64: + return self.entry_float_type + if name in self.call_fields or name == 'GT': + return tcall + elif isinstance(t, tarray): + return tarray(subst_format(name, t.element_type)) + return t + + return tstruct(locus=tstruct(contig=tstr, position=tint32) if self.rg is None else tlocus(self.rg), + alleles=tarray(tstr), + rsid=tstr, + qual=tfloat64, + filters=tset(tstr), + info=tstruct(**{k: parse_type(v) for k, v in self.header['infoFields']}), + **{GVCFPartitionReader.entries_field_name: tarray( + tstruct(**{k: subst_format(k, parse_type(v)) for k, v in self.header['formatFields']}))}, + **uid_fd) + + class PartitionNativeIntervalReader(PartitionReader): def __init__(self, path, table_row_type, uid_field=None): self.path = path @@ -3188,7 +3346,7 @@ def __init__(self, path, table_row_type, uid_field=None): self.uid_field = uid_field def with_uid_field(self, uid_field): - return PartitionNativeIntervalReader(self.path, uid_field) + return PartitionNativeIntervalReader(self.path, self.table_row_type, uid_field) def render(self): return escape_str(json.dumps({"name": "PartitionNativeIntervalReader", diff --git a/hail/python/hail/ir/matrix_ir.py b/hail/python/hail/ir/matrix_ir.py index f5b52feeefe..aea1a70aa1e 100644 --- a/hail/python/hail/ir/matrix_ir.py +++ b/hail/python/hail/ir/matrix_ir.py @@ -1211,18 +1211,3 @@ def _compute_type(self, deep_typecheck): else: return self._type - -class JavaMatrixVectorRef(MatrixIR): - def __init__(self, vec_ref, idx): - super().__init__() - self.vec_ref = vec_ref - self.idx = idx - - def _handle_randomness(self, row_uid_field_name, col_uid_field_name): - raise FatalError('JavaMatrix does not support randomness in consumers') - - def head_str(self): - return f'{self.vec_ref.jid} {self.idx}' - - def _compute_type(self, deep_typecheck): - return self.vec_ref.item_type diff --git a/hail/python/hail/ir/register_functions.py b/hail/python/hail/ir/register_functions.py index 4c2ff2747fa..0c75f67cb19 100644 --- a/hail/python/hail/ir/register_functions.py +++ b/hail/python/hail/ir/register_functions.py @@ -4,6 +4,14 @@ from .ir import register_function, register_seeded_function +vcf_header_type_str = "struct{sampleIDs: array, " \ + "infoFields: array, " \ + "formatFields: array, " \ + "filterAttrs: dict>, " \ + "infoAttrs: dict>, " \ + "formatAttrs: dict>, " \ + "infoFlagFields: array}" + def register_functions(): locusVar = tvariable("R", "locus") @@ -296,3 +304,4 @@ def ndarray_floating_point_divide(arg_type, ret_type): register_function("strftime", (dtype("str"), dtype("int64"), dtype("str")), dtype("str")) register_function("strptime", (dtype("str"), dtype("str"), dtype("str")), dtype("int64")) register_function("index_bgen", (dtype("str"), dtype("str"), dtype("dict"), dtype('bool'), dtype("int32")), dtype("int64"), (dtype("?T"),)) + register_function("getVCFHeader", (dtype("str"), dtype("str"), dtype("str"), dtype("str")), dtype(vcf_header_type_str),) diff --git a/hail/python/hail/methods/__init__.py b/hail/python/hail/methods/__init__.py index e2985acab55..f73ce0f2307 100644 --- a/hail/python/hail/methods/__init__.py +++ b/hail/python/hail/methods/__init__.py @@ -3,8 +3,8 @@ from .impex import (export_elasticsearch, export_gen, export_bgen, export_plink, export_vcf, import_locus_intervals, import_bed, import_fam, grep, import_bgen, import_gen, import_table, import_csv, import_plink, read_matrix_table, read_table, - get_vcf_metadata, import_vcf, import_gvcfs, import_vcfs, index_bgen, - import_matrix_table, import_lines, import_avro) + get_vcf_metadata, import_vcf, index_bgen, import_matrix_table, import_lines, + import_avro, get_vcf_header_info, import_gvcf_interval) from .statgen import (skat, impute_sex, genetic_relatedness_matrix, realized_relationship_matrix, pca, hwe_normalized_pca, _blanczos_pca, _hwe_normalized_blanczos, _spectral_moments, _pca_and_moments, split_multi, filter_alleles, @@ -74,8 +74,7 @@ 'read_table', 'get_vcf_metadata', 'import_vcf', - 'import_vcfs', - 'import_gvcfs', + 'import_gvcf_interval', 'index_bgen', 'balding_nichols_model', 'ld_prune', @@ -93,4 +92,5 @@ 'VEPConfigGRCh37Version85', 'VEPConfigGRCh38Version95', 'vep_json_typ', + 'get_vcf_header_info', ] diff --git a/hail/python/hail/methods/impex.py b/hail/python/hail/methods/impex.py index 65a62800055..3eaf1feedf4 100644 --- a/hail/python/hail/methods/impex.py +++ b/hail/python/hail/methods/impex.py @@ -1,8 +1,6 @@ -import json import os import re from collections import defaultdict -from typing import List import avro.schema from avro.datafile import DataFileReader @@ -12,8 +10,7 @@ from hail import ir from hail.expr import StructExpression, LocusExpression, \ expr_array, expr_float64, expr_str, expr_numeric, expr_call, expr_bool, \ - expr_any, \ - to_expr, analyze + expr_int32, to_expr, analyze from hail.expr.types import hail_type, tarray, tfloat64, tstr, tint32, tstruct, \ tcall, tbool, tint64, tfloat32 from hail.genetics.reference_genome import reference_genome_type @@ -2825,108 +2822,33 @@ def import_vcf(path, return MatrixTable(ir.MatrixRead(reader, drop_cols=drop_samples, drop_row_uids=not _create_row_uids, drop_col_uids=not _create_col_uids)) -@typecheck(path=sequenceof(str), - partitions=expr_any, - call_fields=oneof(str, sequenceof(str)), - entry_float_type=enumeration(tfloat32, tfloat64), - reference_genome=nullable(reference_genome_type), - contig_recoding=nullable(dictof(str, str)), +@typecheck(path=expr_str, + file_num=expr_int32, + contig=expr_str, + start=expr_int32, + end=expr_int32, + header_info=anytype, + call_fields=sequenceof(str), + entry_float_type=hail_type, array_elements_required=bool, + reference_genome=reference_genome_type, + contig_recoding=nullable(dictof(str, str)), skip_invalid_loci=bool, filter=nullable(str), - find_replace=nullable(sized_tupleof(str, str)), - _external_sample_ids=nullable(sequenceof(sequenceof(str))), - _external_header=nullable(str)) -def import_gvcfs(path, - partitions, - call_fields=['PGT'], - entry_float_type=tfloat64, - reference_genome='default', - contig_recoding=None, - array_elements_required=True, - skip_invalid_loci=False, - filter=None, - find_replace=None, - _external_sample_ids=None, - _external_header=None) -> List[MatrixTable]: - """(Experimental) Import multiple vcfs as multiple :class:`.MatrixTable`. - - .. include:: ../_templates/experimental.rst - - All files described by the ``path`` argument must be block gzipped VCF - files. They must all be tabix indexed. Because of this requirement, no - ``force`` or ``force_bgz`` arguments are present. Otherwise, the arguments - to this function are almost identical to :func:`.import_vcf`. However, this - function also requrires a ``partitions`` argument, which is used to divide - and filter the vcfs. It must be an expression or literal of type - ``array}>>``. A partition will be created - for every element of the array. Loci that fall outside of any interval will - not be imported. For example: - - .. code-block:: python - - [hl.Interval(hl.Locus("chr22", 1), hl.Locus("chr22", 5332423), includes_end=True)] - - The ``includes_start`` and ``includes_end`` keys must be ``True``. The - ``contig`` fields must be the same. - - One difference between :func:`.import_gvcfs` and :func:`.import_vcf` is that - :func:`.import_gvcfs` only keys the resulting matrix tables by ``locus`` - rather than ``locus, alleles``. - """ - hl.utils.no_service_backend('import_gvcfs') - rg = reference_genome.name if reference_genome else None - - partitions, partitions_type = hl.utils._dumps_partitions(partitions, hl.tstruct(locus=hl.tlocus(rg), - alleles=hl.tarray(hl.tstr))) - - vector_ref_s = Env.spark_backend('import_vcfs')._jbackend.pyImportVCFs( - wrap_to_list(path), - wrap_to_list(call_fields), - entry_float_type._parsable_string(), - rg, - contig_recoding, - array_elements_required, - skip_invalid_loci, - partitions, partitions_type._parsable_string(), - filter, - find_replace[0] if find_replace is not None else None, - find_replace[1] if find_replace is not None else None, - _external_sample_ids, - _external_header) - vector_ref = json.loads(vector_ref_s) - jir_vref = ir.JIRVectorReference(vector_ref['vector_ir_id'], - vector_ref['length'], - hl.tmatrix._from_json(vector_ref['type'])) - - return [MatrixTable(ir.JavaMatrixVectorRef(jir_vref, idx)) for idx in range(len(jir_vref))] - - -def import_vcfs(path, - partitions, - call_fields=['PGT'], - entry_float_type=tfloat64, - reference_genome='default', - contig_recoding=None, - array_elements_required=True, - skip_invalid_loci=False, - filter=None, - find_replace=None, - _external_sample_ids=None, - _external_header=None) -> List[MatrixTable]: - """This function is deprecated, use :func:`.import_gvcfs` instead""" - return import_gvcfs(path, - partitions, - call_fields, - entry_float_type, - reference_genome, - contig_recoding, - array_elements_required, - skip_invalid_loci, - filter, - find_replace, - _external_sample_ids, - _external_header) + find=nullable(str), + replace=nullable(str)) +def import_gvcf_interval(path, file_num, contig, start, end, header_info, call_fields=[], entry_float_type='float64', + array_elements_required=True, reference_genome='default', contig_recoding=None, + skip_invalid_loci=False, filter=None, find=None, replace=None): + indices, aggs = hl.expr.unify_all(path, file_num, contig, start, end) + stream_ir = ir.ReadPartition(hl.struct(fileNum=file_num, path=path, contig=contig, start=start, end=end)._ir, + ir.GVCFPartitionReader(header_info, call_fields, entry_float_type, + array_elements_required, + reference_genome, contig_recoding or {}, + skip_invalid_loci, filter, find, replace, + None)) + arr = ir.ToArray(stream_ir) + return hl.expr.construct_expr(arr, arr.typ, indices, aggs) @typecheck(path=oneof(str, sequenceof(str)), @@ -3029,6 +2951,18 @@ def index_bgen(path, info(f"indexed {n} sites in {path} at {idx_path}") +@typecheck(path=expr_str, filter=nullable(expr_str), find=nullable(expr_str), replace=nullable(expr_str)) +def get_vcf_header_info(path, filter=None, find=None, replace=None): + from hail.ir.register_functions import vcf_header_type_str + return hl.expr.functions._func( + "getVCFHeader", + hl.dtype(vcf_header_type_str), + path, + hl.missing('str') if filter is None else filter, + hl.missing('str') if find is None else find, + hl.missing('str') if replace is None else replace) + + @typecheck(path=str, _intervals=nullable(sequenceof(anytype)), _filter_intervals=bool, diff --git a/hail/python/hail/methods/qc.py b/hail/python/hail/methods/qc.py index 3e7e09f586c..35c2c66e7cf 100644 --- a/hail/python/hail/methods/qc.py +++ b/hail/python/hail/methods/qc.py @@ -1729,7 +1729,7 @@ def explode_result(alleles): r_ti_tv=nti / ntv) -@typecheck(ds=oneof(hl.MatrixTable, hl.vds.VariantDataset), +@typecheck(ds=oneof(hl.MatrixTable, lambda: hl.vds.VariantDataset), min_af=numeric, max_af=numeric, min_dp=int, @@ -1737,7 +1737,7 @@ def explode_result(alleles): min_gq=int, ref_AF=nullable(expr_float64)) def compute_charr( - ds: Union[hl.MatrixTable, hl.vds.VariantDataset], + ds: Union[hl.MatrixTable, 'hl.vds.VariantDataset'], min_af: float = 0.05, max_af: float = 0.95, min_dp: int = 10, diff --git a/hail/python/hail/vds/combiner/combine.py b/hail/python/hail/vds/combiner/combine.py index f84cf069fca..857ac22ae77 100644 --- a/hail/python/hail/vds/combiner/combine.py +++ b/hail/python/hail/vds/combiner/combine.py @@ -1,10 +1,15 @@ -from typing import Collection, List, Optional, Set, Tuple, Dict +import math +from typing import Collection, Optional, Set +from typing import List, Tuple, Dict import hail as hl from hail import MatrixTable, Table -from hail.ir import Apply, TableMapRows from hail.experimental.function import Function -from hail.experimental.vcf_combiner.vcf_combiner import combine_gvcfs, localize, parse_as_fields, unlocalize +from hail.expr import StructExpression, unify_all, construct_expr +from hail.expr.expressions import expr_bool, expr_str +from hail.genetics.reference_genome import reference_genome_type +from hail.ir import Apply, TableMapRows +from hail.typecheck import oneof, sequenceof, typecheck from ..variant_dataset import VariantDataset _transform_variant_function_map: Dict[Tuple[hl.HailType, Tuple[str, ...]], Function] = {} @@ -103,6 +108,134 @@ def defined_entry_fields(mt: MatrixTable, sample=None) -> Set[str]: return set(k for k in mt.entry if used[k]) +def make_reference_stream(stream, entry_to_keep: Collection[str]): + stream = stream.filter(lambda elt: hl.is_defined(elt.info.END)) + entry_key = tuple(sorted(entry_to_keep)) # hashable stable value + + def make_entry_struct(e, row): + handled_fields = dict() + # we drop PL by default, but if `entry_to_keep` has it then PL needs to be + # turned into LPL + handled_names = {'AD', 'PL'} + + if 'AD' in entry_to_keep: + handled_fields['LAD'] = e['AD'][:1] + if 'PL' in entry_to_keep: + handled_fields['LPL'] = e['PL'][:1] + + reference_fields = {k: v for k, v in e.items() + if k in entry_to_keep and k not in handled_names} + return (hl.case() + .when(e.GT.is_hom_ref(), + hl.struct(END=row.info.END, **reference_fields, **handled_fields)) + .or_error('found END with non reference-genotype at' + hl.str(row.locus))) + + row_type = stream.dtype.element_type + transform_row = _transform_reference_fuction_map.get((row_type, entry_key)) + if transform_row is None or not hl.current_backend()._is_registered_ir_function_name(transform_row._name): + transform_row = hl.experimental.define_function( + lambda row: hl.struct( + locus=row.locus, + __entries=row.__entries.map( + lambda e: make_entry_struct(e, row))), + row_type) + _transform_reference_fuction_map[row_type, entry_key] = transform_row + + return stream.map(lambda row: hl.struct( + locus=row.locus, + __entries=row.__entries.map( + lambda e: make_entry_struct(e, row)))) + + +def make_variant_stream(stream, info_to_keep): + info_t = stream.dtype.element_type['info'] + if info_to_keep is None: + info_to_keep = [] + if not info_to_keep: + info_to_keep = [name for name in info_t if name not in ['END', 'DP']] + info_key = tuple(sorted(info_to_keep)) # hashable stable value + stream = stream.filter(lambda elt: hl.is_missing(elt.info.END)) + + row_type = stream.dtype.element_type + + transform_row = _transform_variant_function_map.get((row_type, info_key)) + if transform_row is None or not hl.current_backend()._is_registered_ir_function_name(transform_row._name): + def get_lgt(e, n_alleles, has_non_ref, row): + index = e.GT.unphased_diploid_gt_index() + n_no_nonref = n_alleles - hl.int(has_non_ref) + triangle_without_nonref = hl.triangle(n_no_nonref) + return (hl.case() + .when(e.GT.is_haploid(), + hl.or_missing(e.GT[0] < n_no_nonref, e.GT)) + .when(index < triangle_without_nonref, e.GT) + .when(index < hl.triangle(n_alleles), hl.missing('call')) + .or_error('invalid GT ' + hl.str(e.GT) + ' at site ' + hl.str(row.locus))) + + def make_entry_struct(e, alleles_len, has_non_ref, row): + handled_fields = dict() + handled_names = {'LA', 'gvcf_info', + 'LAD', 'AD', + 'LGT', 'GT', + 'LPL', 'PL', + 'LPGT', 'PGT'} + + if 'GT' not in e: + raise hl.utils.FatalError("the Hail GVCF combiner expects GVCFs to have a 'GT' field in FORMAT.") + + handled_fields['LA'] = hl.range(0, alleles_len - hl.if_else(has_non_ref, 1, 0)) + handled_fields['LGT'] = get_lgt(e, alleles_len, has_non_ref, row) + if 'AD' in e: + handled_fields['LAD'] = hl.if_else(has_non_ref, e.AD[:-1], e.AD) + if 'PGT' in e: + handled_fields['LPGT'] = e.PGT + if 'PL' in e: + handled_fields['LPL'] = hl.if_else(has_non_ref, + hl.if_else(alleles_len > 2, + e.PL[:-alleles_len], + hl.missing(e.PL.dtype)), + hl.if_else(alleles_len > 1, + e.PL, + hl.missing(e.PL.dtype))) + handled_fields['RGQ'] = hl.if_else( + has_non_ref, + hl.if_else(e.GT.is_haploid(), + e.PL[alleles_len - 1], + e.PL[hl.call(0, alleles_len - 1).unphased_diploid_gt_index()]), + hl.missing(e.PL.dtype.element_type)) + + handled_fields['gvcf_info'] = (hl.case() + .when(hl.is_missing(row.info.END), + hl.struct(**( + parse_as_fields( + row.info.select(*info_to_keep), + has_non_ref) + ))) + .or_missing()) + + pass_through_fields = {k: v for k, v in e.items() if k not in handled_names} + return hl.struct(**handled_fields, **pass_through_fields) + + transform_row = hl.experimental.define_function( + lambda row: hl.rbind( + hl.len(row.alleles), '' == row.alleles[-1], + lambda alleles_len, has_non_ref: hl.struct( + locus=row.locus, + alleles=hl.if_else(has_non_ref, row.alleles[:-1], row.alleles), + **({'rsid': row.rsid} if 'rsid' in row else {}), + __entries=row.__entries.map( + lambda e: make_entry_struct(e, alleles_len, has_non_ref, row)))), + row_type) + _transform_variant_function_map[row_type, info_key] = transform_row + + from hail.expr import construct_expr + from hail.utils.java import Env + uid = Env.get_uid() + map_ir = hl.ir.ToArray(hl.ir.StreamMap(hl.ir.ToStream(stream._ir), uid, + Apply(transform_row._name, transform_row._ret_type, + hl.ir.Ref(uid, type=row_type)))) + return construct_expr(map_ir, map_ir.typ, stream._indices, stream._aggregations) + + def make_reference_matrix_table(mt: MatrixTable, entry_to_keep: Collection[str] ) -> MatrixTable: @@ -123,11 +256,11 @@ def make_entry_struct(e, row): reference_fields = {k: v for k, v in e.items() if k in entry_to_keep and k not in handled_names} return (hl.case() - .when(e.GT.is_hom_ref(), - hl.struct(END=row.info.END, **reference_fields, **handled_fields)) - .or_error('found END with non reference-genotype at' + hl.str(row.locus))) + .when(e.GT.is_hom_ref(), + hl.struct(END=row.info.END, **reference_fields, **handled_fields)) + .or_error('found END with non reference-genotype at' + hl.str(row.locus))) - mt = localize(mt) + mt = localize(mt).key_by('locus') transform_row = _transform_reference_fuction_map.get((mt.row.dtype, entry_key)) if transform_row is None or not hl.current_backend()._is_registered_ir_function_name(transform_row._name): transform_row = hl.experimental.define_function( @@ -144,10 +277,10 @@ def make_entry_struct(e, row): def transform_gvcf(mt: MatrixTable, reference_entry_fields_to_keep: Collection[str], info_to_keep: Optional[Collection[str]] = None) -> VariantDataset: - """Transforms a GVCF into a sparse matrix table + """Transforms a GVCF into a single sample VariantDataSet - The input to this should be some result of either :func:`.import_vcf` or - :func:`.import_gvcfs` with ``array_elements_required=False``. + The input to this should be some result of :func:`.import_vcf` + ``array_elements_required=False``. There is an assumption that this function will be called on a matrix table with one column (or a localized table version of the same). @@ -189,7 +322,16 @@ def transform_gvcf(mt: MatrixTable, def combine_r(ts, ref_block_max_len_field): - merge_function = _merge_function_map.get((ts.row.dtype, ts.globals.dtype)) + ts = Table(TableMapRows(ts._tir, combine_reference_row(ts.row, ts.globals)._ir)) + + global_fds = {'__cols': hl.flatten(ts.g.map(lambda g: g.__cols))} + if ref_block_max_len_field is not None: + global_fds[ref_block_max_len_field] = hl.max(ts.g.map(lambda g: g[ref_block_max_len_field])) + return ts.transmute_globals(**global_fds) + + +def combine_reference_row(row, globals): + merge_function = _merge_function_map.get((row.dtype, globals)) if merge_function is None or not hl.current_backend()._is_registered_ir_function_name(merge_function._name): merge_function = hl.experimental.define_function( lambda row, gbl: @@ -201,17 +343,14 @@ def combine_r(ts, ref_block_max_len_field): hl.range(0, hl.len(gbl.g[i].__cols)) .map(lambda _: hl.missing(row.data[i].__entries.dtype.element_type)), row.data[i].__entries))), - ts.row.dtype, ts.globals.dtype) - _merge_function_map[(ts.row.dtype, ts.globals.dtype)] = merge_function - ts = Table(TableMapRows(ts._tir, Apply(merge_function._name, - merge_function._ret_type, - ts.row._ir, - ts.globals._ir))) - - global_fds = {'__cols': hl.flatten(ts.g.map(lambda g: g.__cols))} - if ref_block_max_len_field is not None: - global_fds[ref_block_max_len_field] = hl.max(ts.g.map(lambda g: g[ref_block_max_len_field])) - return ts.transmute_globals(**global_fds) + row.dtype, globals.dtype) + _merge_function_map[(row.dtype, globals.dtype)] = merge_function + apply_ir = Apply(merge_function._name, + merge_function._ret_type, + row._ir, + globals._ir) + indices, aggs = unify_all(row, globals) + return construct_expr(apply_ir, apply_ir.typ, indices, aggs) def combine_references(mts: List[MatrixTable]) -> MatrixTable: @@ -237,3 +376,289 @@ def combine_variant_datasets(vdss: List[VariantDataset]) -> VariantDataset: variants = combine_gvcfs(no_variant_key) return VariantDataset(reference, variants._key_rows_by_assert_sorted('locus', 'alleles')) + + +_transform_rows_function_map: Dict[Tuple[hl.HailType], Function] = {} +_merge_function_map: Dict[Tuple[hl.HailType, hl.HailType], Function] = {} + + +@typecheck(string=expr_str, has_non_ref=expr_bool) +def parse_as_ints(string, has_non_ref): + ints = string.split(r'\|') + ints = hl.if_else(has_non_ref, ints[:-1], ints) + return ints.map(lambda i: hl.if_else((hl.len(i) == 0) | (i == '.'), hl.missing(hl.tint32), hl.int32(i))) + + +@typecheck(string=expr_str, has_non_ref=expr_bool) +def parse_as_doubles(string, has_non_ref): + ints = string.split(r'\|') + ints = hl.if_else(has_non_ref, ints[:-1], ints) + return ints.map(lambda i: hl.if_else((hl.len(i) == 0) | (i == '.'), hl.missing(hl.tfloat64), hl.float64(i))) + + +@typecheck(string=expr_str, has_non_ref=expr_bool) +def parse_as_sb_table(string, has_non_ref): + ints = string.split(r'\|') + ints = hl.if_else(has_non_ref, ints[:-1], ints) + return ints.map(lambda xs: xs.split(",").map(hl.int32)) + + +@typecheck(string=expr_str, has_non_ref=expr_bool) +def parse_as_ranksum(string, has_non_ref): + typ = hl.ttuple(hl.tfloat64, hl.tint32) + items = string.split(r'\|') + items = hl.if_else(has_non_ref, items[:-1], items) + return items.map(lambda s: hl.if_else( + (hl.len(s) == 0) | (s == '.'), + hl.missing(typ), + hl.rbind(s.split(','), lambda ss: hl.if_else( + hl.len(ss) != 2, # bad field, possibly 'NaN', just set it null + hl.missing(hl.ttuple(hl.tfloat64, hl.tint32)), + hl.tuple([hl.float64(ss[0]), hl.int32(ss[1])]))))) + + +_as_function_map = { + 'AS_QUALapprox': parse_as_ints, + 'AS_RAW_MQ': parse_as_doubles, + 'AS_RAW_MQRankSum': parse_as_ranksum, + 'AS_RAW_ReadPosRankSum': parse_as_ranksum, + 'AS_SB_TABLE': parse_as_sb_table, + 'AS_VarDP': parse_as_ints, +} + + +def parse_as_fields(info, has_non_ref): + return hl.struct(**{f: info[f] if f not in _as_function_map + else _as_function_map[f](info[f], has_non_ref) for f in info}) + + +def localize(mt): + if isinstance(mt, MatrixTable): + return mt._localize_entries('__entries', '__cols') + return mt + + +def unlocalize(mt): + if isinstance(mt, Table): + return mt._unlocalize_entries('__entries', '__cols', ['s']) + return mt + + +def merge_alleles(alleles): + from hail.expr.functions import _num_allele_type, _allele_ints + return hl.rbind( + alleles.map(lambda a: hl.or_else(a[0], '')) + .fold(lambda s, t: hl.if_else(hl.len(s) > hl.len(t), s, t), ''), + lambda ref: + hl.rbind( + alleles.map( + lambda al: hl.rbind( + al[0], + lambda r: + hl.array([ref]).extend( + al[1:].map( + lambda a: + hl.rbind( + _num_allele_type(r, a), + lambda at: + hl.if_else( + (_allele_ints['SNP'] == at) + | (_allele_ints['Insertion'] == at) + | (_allele_ints['Deletion'] == at) + | (_allele_ints['MNP'] == at) + | (_allele_ints['Complex'] == at), + a + ref[hl.len(r):], + a)))))), + lambda lal: + hl.struct( + globl=hl.array([ref]).extend(hl.array(hl.set(hl.flatten(lal)).remove(ref))), + local=lal))) + + +def combine_variant_rows(row, globals): + def renumber_entry(entry, old_to_new) -> StructExpression: + # global index of alternate (non-ref) alleles + return entry.annotate(LA=entry.LA.map(lambda lak: old_to_new[lak])) + + merge_function = _merge_function_map.get((row.dtype, globals.dtype)) + if merge_function is None or not hl.current_backend()._is_registered_ir_function_name(merge_function._name): + merge_function = hl.experimental.define_function( + lambda row, gbl: + hl.rbind( + merge_alleles(row.data.map(lambda d: d.alleles)), + lambda alleles: + hl.struct( + locus=row.locus, + alleles=alleles.globl, + **({'rsid': hl.find(hl.is_defined, row.data.map( + lambda d: d.rsid))} if 'rsid' in row.data.dtype.element_type else {}), + __entries=hl.bind( + lambda combined_allele_index: + hl.range(0, hl.len(row.data)).flatmap( + lambda i: + hl.if_else(hl.is_missing(row.data[i].__entries), + hl.range(0, hl.len(gbl.g[i].__cols)) + .map(lambda _: hl.missing(row.data[i].__entries.dtype.element_type)), + hl.bind( + lambda old_to_new: row.data[i].__entries.map( + lambda e: renumber_entry(e, old_to_new)), + hl.range(0, hl.len(alleles.local[i])).map( + lambda j: combined_allele_index[alleles.local[i][j]])))), + hl.dict(hl.range(0, hl.len(alleles.globl)).map( + lambda j: hl.tuple([alleles.globl[j], j])))))), + row.dtype, globals.dtype) + _merge_function_map[(row.dtype, globals.dtype)] = merge_function + indices, aggs = unify_all(row, globals) + apply_ir = Apply(merge_function._name, + merge_function._ret_type, + row._ir, + globals._ir) + return construct_expr(apply_ir, apply_ir.typ, indices, aggs) + + +def combine(ts): + ts = Table(TableMapRows(ts._tir, combine_variant_rows( + ts.row, + ts.globals)._ir)) + return ts.transmute_globals(__cols=hl.flatten(ts.g.map(lambda g: g.__cols))) + + +@typecheck(mts=sequenceof(oneof(Table, MatrixTable))) +def combine_gvcfs(mts): + """Merges gvcfs and/or sparse matrix tables + + Parameters + ---------- + mts : :obj:`List[Union[Table, MatrixTable]]` + The matrix tables (or localized versions) to combine + + Returns + ------- + :class:`.MatrixTable` + + Notes + ----- + All of the input tables/matrix tables must have the same partitioning. This + module provides no method of repartitioning data. + """ + ts = hl.Table.multi_way_zip_join([localize(mt) for mt in mts], 'data', 'g') + combined = combine(ts) + return unlocalize(combined) + + +@typecheck(mt=hl.MatrixTable, desired_average_partition_size=int, tmp_path=str) +def calculate_new_intervals(mt, desired_average_partition_size: int, tmp_path: str): + """takes a table, keyed by ['locus', ...] and produces a list of intervals suitable + for repartitioning a combiner matrix table. + + Parameters + ---------- + mt : :class:`.MatrixTable` + Sparse MT intermediate. + desired_average_partition_size : :obj:`int` + Average target number of rows for each partition. + tmp_path : :obj:`str` + Temporary path for scan checkpointing. + + Returns + ------- + (:obj:`List[Interval]`, :obj:`.Type`) + """ + assert list(mt.row_key) == ['locus'] + assert isinstance(mt.locus.dtype, hl.tlocus) + reference_genome = mt.locus.dtype.reference_genome + end = hl.Locus(reference_genome.contigs[-1], + reference_genome.lengths[reference_genome.contigs[-1]], + reference_genome=reference_genome) + + (n_rows, n_cols) = mt.count() + + if n_rows == 0: + raise ValueError('empty table!') + + # split by a weight function that takes into account the number of + # dense entries per row. However, give each row some base weight + # to prevent densify computations from becoming unbalanced (these + # scale roughly linearly with N_ROW * N_COL) + ht = mt.select_rows(weight=hl.agg.count() + (n_cols // 25) + 1).rows().checkpoint(tmp_path) + + total_weight = ht.aggregate(hl.agg.sum(ht.weight)) + partition_weight = int(total_weight / (n_rows / desired_average_partition_size)) + + ht = ht.annotate(cumulative_weight=hl.scan.sum(ht.weight), + last_weight=hl.scan._prev_nonnull(ht.weight), + row_idx=hl.scan.count()) + + def partition_bound(x): + return x - (x % hl.int64(partition_weight)) + + at_partition_bound = partition_bound(ht.cumulative_weight) != partition_bound(ht.cumulative_weight - ht.last_weight) + + ht = ht.filter(at_partition_bound | (ht.row_idx == n_rows - 1)) + ht = ht.annotate(start=hl.or_else( + hl.scan._prev_nonnull(hl.locus_from_global_position(ht.locus.global_position() + 1, + reference_genome=reference_genome)), + hl.locus_from_global_position(0, reference_genome=reference_genome))) + ht = ht.select( + interval=hl.interval(start=hl.struct(locus=ht.start), end=hl.struct(locus=ht.locus), includes_end=True)) + + intervals_dtype = hl.tarray(ht.interval.dtype) + intervals = ht.aggregate(hl.agg.collect(ht.interval)) + last_st = hl.eval( + hl.locus_from_global_position(hl.literal(intervals[-1].end.locus).global_position() + 1, + reference_genome=reference_genome)) + interval = hl.Interval(start=hl.Struct(locus=last_st), end=hl.Struct(locus=end), includes_end=True) + intervals.append(interval) + return intervals, intervals_dtype + + +@typecheck(reference_genome=reference_genome_type, interval_size=int) +def calculate_even_genome_partitioning(reference_genome, interval_size) -> List[hl.utils.Interval]: + """create a list of locus intervals suitable for importing and merging gvcfs. + + Parameters + ---------- + reference_genome: :class:`str` or :class:`.ReferenceGenome`, + Reference genome to use. NOTE: only GRCh37 and GRCh38 references + are supported. + interval_size: :obj:`int` The ceiling and rough target of interval size. + Intervals will never be larger than this, but may be smaller. + + Returns + ------- + :obj:`List[Interval]` + """ + + def calc_parts(contig): + def locus_interval(start, end): + return hl.Interval( + start=hl.Locus(contig=contig, position=start, reference_genome=reference_genome), + end=hl.Locus(contig=contig, position=end, reference_genome=reference_genome), + includes_end=True) + + contig_length = reference_genome.lengths[contig] + n_parts = math.ceil(contig_length / interval_size) + real_size = math.ceil(contig_length / n_parts) + n = 1 + intervals = [] + while n < contig_length: + start = n + end = min(n + real_size, contig_length) + intervals.append(locus_interval(start, end)) + n = end + 1 + + return intervals + + if reference_genome.name == 'GRCh37': + contigs = [f'{i}' for i in range(1, 23)] + ['X', 'Y', 'MT'] + elif reference_genome.name == 'GRCh38': + contigs = [f'chr{i}' for i in range(1, 23)] + ['chrX', 'chrY', 'chrM'] + else: + raise ValueError( + f"Unsupported reference genome '{reference_genome.name}', " + "only 'GRCh37' and 'GRCh38' are supported") + + intervals = [] + for ctg in contigs: + intervals.extend(calc_parts(ctg)) + return intervals diff --git a/hail/python/hail/vds/combiner/variant_dataset_combiner.py b/hail/python/hail/vds/combiner/variant_dataset_combiner.py index f47e465bfb3..d45c82e5a4a 100644 --- a/hail/python/hail/vds/combiner/variant_dataset_combiner.py +++ b/hail/python/hail/vds/combiner/variant_dataset_combiner.py @@ -4,18 +4,16 @@ import os import sys import uuid - from math import floor, log from typing import Collection, Dict, List, NamedTuple, Optional, Union import hail as hl - from hail.expr import HailType, tmatrix from hail.utils import Interval from hail.utils.java import info, warning -from hail.experimental.vcf_combiner.vcf_combiner import calculate_even_genome_partitioning, \ - calculate_new_intervals -from .combine import combine_variant_datasets, transform_gvcf, defined_entry_fields +from .combine import combine_variant_datasets, transform_gvcf, defined_entry_fields, make_variant_stream, \ + make_reference_stream, combine_r, calculate_even_genome_partitioning, \ + calculate_new_intervals, combine class VDSMetadata(NamedTuple): @@ -475,21 +473,79 @@ def _step_gvcfs(self): self._gvcf_sample_names = self._gvcf_sample_names[self._gvcf_batch_size * step:] else: sample_names = None + header_file = self._gvcf_external_header or files_to_merge[0] + header_info = hl.eval(hl.get_vcf_header_info(header_file)) merge_vds = [] merge_n_samples = [] - vcfs = [transform_gvcf(vcf, - reference_entry_fields_to_keep=self._gvcf_reference_entry_fields_to_keep, - info_to_keep=self._gvcf_info_to_keep) - for vcf in hl.import_gvcfs(files_to_merge, - self._gvcf_import_intervals, - array_elements_required=False, - _external_header=self._gvcf_external_header, - _external_sample_ids=[[name] for name in sample_names] if sample_names is not None else None, - reference_genome=self._reference_genome, - contig_recoding=self._contig_recoding)] - while vcfs: - merging, vcfs = vcfs[:step], vcfs[step:] - merge_vds.append(combine_variant_datasets(merging)) + + intervals_literal = hl.literal([hl.Struct(contig=i.start.contig, start=i.start.position, end=i.end.position) for + i in self._gvcf_import_intervals]) + + partition_interval_point_type = hl.tstruct(locus=hl.tlocus(self._reference_genome)) + partition_intervals = [hl.Interval(start=hl.Struct(locus=i.start), + end=hl.Struct(locus=i.end), + includes_start=i.includes_start, + includes_end=i.includes_end, + point_type=partition_interval_point_type) for i in + self._gvcf_import_intervals] + vcfs = files_to_merge + if sample_names is None: + vcfs_lit = hl.literal(vcfs) + range_ht = hl.utils.range_table(len(vcfs), n_partitions=min(len(vcfs), 32)) + + range_ht = range_ht.annotate(sample_id=hl.rbind(hl.get_vcf_header_info(vcfs_lit[range_ht.idx]), + lambda header: header.sampleIDs[0])) + + sample_ids = range_ht.aggregate(hl.agg.collect(range_ht.sample_id)) + else: + sample_ids = sample_names + for start in range(0, len(vcfs), step): + ids = sample_ids[start:start + step] + merging = vcfs[start:start + step] + + reference_ht = hl.Table._generate(contexts=intervals_literal, + partitions=partition_intervals, + rowfn=lambda interval, globals: + hl._zip_join_producers(hl.enumerate(hl.literal(merging)), + lambda idx_and_path: make_reference_stream( + hl.import_gvcf_interval( + idx_and_path[1], idx_and_path[0], + interval.contig, + interval.start, interval.end, header_info, + array_elements_required=False, + reference_genome=self._reference_genome, + contig_recoding=self._contig_recoding), + self._gvcf_reference_entry_fields_to_keep), + ['locus'], + lambda k, v: k.annotate(data=v)), + globals=hl.struct( + g=hl.literal(ids).map(lambda s: hl.struct(__cols=[hl.struct(s=s)])))) + reference_ht = combine_r(reference_ht, ref_block_max_len_field=None) # compute max length at the end + + variant_ht = hl.Table._generate(contexts=intervals_literal, + partitions=partition_intervals, + rowfn=lambda interval, globals: + hl._zip_join_producers(hl.enumerate(hl.literal(merging)), + lambda idx_and_path: make_variant_stream( + hl.import_gvcf_interval( + idx_and_path[1], idx_and_path[0], + interval.contig, + interval.start, interval.end, header_info, + array_elements_required=False, + reference_genome=self._reference_genome, + contig_recoding=self._contig_recoding), + self._gvcf_info_to_keep), + ['locus'], + lambda k, v: k.annotate(data=v)), + globals=hl.struct( + g=hl.literal(ids).map(lambda s: hl.struct(__cols=[hl.struct(s=s)])))) + variant_ht = combine(variant_ht) + vds = hl.vds.VariantDataset(reference_ht._unlocalize_entries('__entries', '__cols', ['s']), + variant_ht._unlocalize_entries('__entries', '__cols', + ['s'])._key_rows_by_assert_sorted('locus', + 'alleles')) + + merge_vds.append(vds) merge_n_samples.append(len(merging)) if self.finished and len(merge_vds) == 1: self._write_final(merge_vds[0]) diff --git a/hail/python/hail/vds/methods.py b/hail/python/hail/vds/methods.py index be8bed205c6..c80c950a00a 100644 --- a/hail/python/hail/vds/methods.py +++ b/hail/python/hail/vds/methods.py @@ -238,7 +238,7 @@ def allele_type(ref, alt): vmt = vds.variant_data if 'GT' not in vmt.entry: - vmt = vmt.annotate_entries(GT=hl.experimental.lgt_to_gt(vmt.LGT, vmt.LA)) + vmt = vmt.annotate_entries(GT=hl.vds.lgt_to_gt(vmt.LGT, vmt.LA)) vmt = vmt.annotate_rows(**{ variant_ac: hl.agg.call_stats(vmt.GT, vmt.alleles).AC, diff --git a/hail/python/test/hail/experimental/test_vcf_combiner.py b/hail/python/test/hail/experimental/test_vcf_combiner.py deleted file mode 100644 index 6cd293075b1..00000000000 --- a/hail/python/test/hail/experimental/test_vcf_combiner.py +++ /dev/null @@ -1,161 +0,0 @@ -import os - -import hail as hl -from hail.experimental.vcf_combiner import vcf_combiner as vc -from hail.utils.java import Env -from hail.utils.misc import new_temp_file -from ..helpers import resource, fails_local_backend, fails_service_backend - - -all_samples = ['HG00308', 'HG00592', 'HG02230', 'NA18534', 'NA20760', - 'NA18530', 'HG03805', 'HG02223', 'HG00637', 'NA12249', - 'HG02224', 'NA21099', 'NA11830', 'HG01378', 'HG00187', - 'HG01356', 'HG02188', 'NA20769', 'HG00190', 'NA18618', - 'NA18507', 'HG03363', 'NA21123', 'HG03088', 'NA21122', - 'HG00373', 'HG01058', 'HG00524', 'NA18969', 'HG03833', - 'HG04158', 'HG03578', 'HG00339', 'HG00313', 'NA20317', - 'HG00553', 'HG01357', 'NA19747', 'NA18609', 'HG01377', - 'NA19456', 'HG00590', 'HG01383', 'HG00320', 'HG04001', - 'NA20796', 'HG00323', 'HG01384', 'NA18613', 'NA20802'] - - -@fails_service_backend() -@fails_local_backend() -def test_1kg_chr22(): - out_file = new_temp_file(extension='mt') - - sample_names = all_samples[:5] - paths = [os.path.join(resource('gvcfs'), '1kg_chr22', f'{s}.hg38.g.vcf.gz') for s in sample_names] - vc.run_combiner(paths, - out_file=out_file, - tmp_path=Env.hc()._tmpdir, - branch_factor=2, - batch_size=2, - reference_genome='GRCh38', - use_exome_default_intervals=True) - - sample_data = dict() - for sample, path in zip(sample_names, paths): - ht = hl.import_vcf(path, force_bgz=True, reference_genome='GRCh38').localize_entries('entries') - n, n_variant = ht.aggregate((hl.agg.count(), hl.agg.count_where(ht.entries[0].GT.is_non_ref()))) - sample_data[sample] = (n, n_variant) - - mt = hl.read_matrix_table(out_file) - mt = mt.annotate_cols(n=hl.agg.count(), n_variant=hl.agg.count_where( - mt.LGT.is_non_ref())) # annotate the number of non-missing records - - combined_results = hl.tuple([mt.s, mt.n, mt.n_variant]).collect() - assert len(combined_results) == len(sample_names) - - for sample, n, n_variant in combined_results: - true_n, true_n_variant = sample_data[sample] - assert n == true_n, sample - assert n_variant == true_n_variant, sample - -def default_exome_intervals(rg): - return vc.calculate_even_genome_partitioning(rg, 2 ** 32) # 4 billion, larger than any contig - -@fails_service_backend() -@fails_local_backend() -def test_gvcf_1k_same_as_import_vcf(): - path = os.path.join(resource('gvcfs'), '1kg_chr22', f'HG00308.hg38.g.vcf.gz') - [mt] = hl.import_gvcfs([path], default_exome_intervals('GRCh38'), reference_genome='GRCh38') - assert mt._same(hl.import_vcf(path, force_bgz=True, reference_genome='GRCh38').key_rows_by('locus')) - -@fails_service_backend() -@fails_local_backend() -def test_import_vcfs_still_works(): - path = os.path.join(resource('gvcfs'), '1kg_chr22', f'HG00308.hg38.g.vcf.gz') - [mt] = hl.import_vcfs([path], default_exome_intervals('GRCh38'), reference_genome='GRCh38') - assert mt._same(hl.import_vcf(path, force_bgz=True, reference_genome='GRCh38').key_rows_by('locus')) - -@fails_service_backend() -@fails_local_backend() -def test_gvcf_subset_same_as_import_vcf(): - path = os.path.join(resource('gvcfs'), 'subset', f'HG00187.hg38.g.vcf.gz') - [mt] = hl.import_gvcfs([path], default_exome_intervals('GRCh38'), reference_genome='GRCh38') - assert mt._same(hl.import_vcf(path, force_bgz=True, reference_genome='GRCh38').key_rows_by('locus')) - -@fails_service_backend() -@fails_local_backend() -def test_key_by_locus_alleles(): - out_file = new_temp_file(extension='mt') - - sample_names = all_samples[:5] - paths = [os.path.join(resource('gvcfs'), '1kg_chr22', f'{s}.hg38.g.vcf.gz') for s in sample_names] - vc.run_combiner(paths, - out_file=out_file, - tmp_path=Env.hc()._tmpdir, - reference_genome='GRCh38', - key_by_locus_and_alleles=True, - use_exome_default_intervals=True) - - mt = hl.read_matrix_table(out_file) - assert(list(mt.row_key) == ['locus', 'alleles']) - mt._force_count_rows() - - -@fails_service_backend() -@fails_local_backend() -def test_non_ref_alleles_set_to_missing(): - path = os.path.join(resource('gvcfs'), 'non_ref_call.g.vcf.gz') - out_file = new_temp_file(extension='mt') - vc.run_combiner([path, path], - out_file=out_file, - tmp_path=Env.hc()._tmpdir, - branch_factor=2, - batch_size=2, - reference_genome='GRCh38', - use_exome_default_intervals=True) - - mt = hl.read_matrix_table(out_file) - n_alleles = hl.len(mt.alleles) - gt_idx = hl.experimental.lgt_to_gt(mt.LGT, mt.LA).unphased_diploid_gt_index() - assert mt.aggregate_entries( - hl.agg.all(gt_idx < (n_alleles * (n_alleles + 1)) / 2)) - -@fails_service_backend() -@fails_local_backend() -def test_contig_recoding(): - path1 = os.path.join(resource('gvcfs'), 'recoding', 'HG00187.hg38.g.vcf.gz') - path2 = os.path.join(resource('gvcfs'), 'recoding', 'HG00187.hg38.recoded.g.vcf.gz') - - out_file_1 = new_temp_file(extension='mt') - out_file_2 = new_temp_file(extension='mt') - - vc.run_combiner([path1, path1], out_file_1, - Env.hc()._tmpdir, - reference_genome='GRCh38', - use_exome_default_intervals=True) - vc.run_combiner([path2, path2], out_file_2, - Env.hc()._tmpdir, - reference_genome='GRCh38', - contig_recoding={'22': 'chr22'}, - use_exome_default_intervals=True) - - mt1 = hl.read_matrix_table(out_file_1) - mt2 = hl.read_matrix_table(out_file_2) - - assert mt1.count() == mt2.count() - assert mt1._same(mt2) - -@fails_service_backend() -@fails_local_backend() -def test_sample_override(): - out_file = new_temp_file(extension='mt') - - sample_names = all_samples[:5] - new_names = [f'S{i}' for i, _ in enumerate(sample_names)] - paths = [os.path.join(resource('gvcfs'), '1kg_chr22', f'{s}.hg38.g.vcf.gz') for s in sample_names] - header_path = paths[0] - vc.run_combiner(paths, - out_file=out_file, - tmp_path=Env.hc()._tmpdir, - reference_genome='GRCh38', - header=header_path, - sample_names=new_names, - key_by_locus_and_alleles=True, - use_exome_default_intervals=True) - mt_cols = hl.read_matrix_table(out_file).key_cols_by().cols() - mt_names = mt_cols.aggregate(hl.agg.collect(mt_cols.s)) - assert new_names == mt_names diff --git a/hail/python/test/hail/expr/test_expr.py b/hail/python/test/hail/expr/test_expr.py index def5ba76948..852cf064d56 100644 --- a/hail/python/test/hail/expr/test_expr.py +++ b/hail/python/test/hail/expr/test_expr.py @@ -4160,4 +4160,29 @@ def test_reservoir_sampling(): def test_local_agg(): x = hl.literal([1,2,3,4]) - assert hl.eval(x.aggregate(lambda x: hl.agg.sum(x))) == 10 \ No newline at end of file + assert hl.eval(x.aggregate(lambda x: hl.agg.sum(x))) == 10 + + +def test_zip_join_producers(): + contexts = hl.literal([1,2,3]) + zj = hl._zip_join_producers(contexts, + lambda i: hl.range(i).map(lambda x: hl.struct(k=x, stream_id=i)), + ['k'], + lambda k, vals: k.annotate(vals=vals)) + assert hl.eval(zj) == [ + hl.utils.Struct(k=0, vals=[ + hl.utils.Struct(k=0, stream_id=1), + hl.utils.Struct(k=0, stream_id=2), + hl.utils.Struct(k=0, stream_id=3), + ]), + hl.utils.Struct(k=1, vals=[ + None, + hl.utils.Struct(k=1, stream_id=2), + hl.utils.Struct(k=1, stream_id=3), + ]), + hl.utils.Struct(k=2, vals=[ + None, + None, + hl.utils.Struct(k=2, stream_id=3), + ]) + ] diff --git a/hail/python/test/hail/methods/test_impex.py b/hail/python/test/hail/methods/test_impex.py index eef22331f71..74b8cf0c5ee 100644 --- a/hail/python/test/hail/methods/test_impex.py +++ b/hail/python/test/hail/methods/test_impex.py @@ -370,36 +370,14 @@ def test_import_gvcfs(self): path = resource('sample.vcf.bgz') self.import_gvcfs_sample_vcf(path) - @fails_service_backend() - @fails_local_backend() - def test_import_gvcfs_subset(self): - path = resource('sample.vcf.bgz') - parts = [ - hl.Interval(start=hl.Struct(locus=hl.Locus('20', 13509136)), - end=hl.Struct(locus=hl.Locus('20', 16493533)), - includes_end=True) - ] - vcf1 = hl.import_vcf(path).key_rows_by('locus') - vcf2 = hl.import_gvcfs([path], parts)[0] - interval = [hl.parse_locus_interval('[20:13509136-16493533]')] - filter1 = hl.filter_intervals(vcf1, interval) - self.assertTrue(vcf2._same(filter1)) - self.assertEqual(len(parts), vcf2.n_partitions()) - - @fails_service_backend() - @fails_local_backend() def test_import_gvcfs_long_line(self): import bz2 + fs = hl.current_backend().fs path = resource('gvcfs/long_line.g.vcf.gz') - parts = [ - hl.Interval(start=hl.Struct(locus=hl.Locus('1', 1)), - end=hl.Struct(locus=hl.Locus('1', 1_000_000)), - includes_end=True) - ] - [vcf] = hl.import_gvcfs([path], parts) + vcf = hl.import_vcf(path, force_bgz=True) [data] = vcf.info.Custom.collect() - with bz2.open(resource('gvcfs/long_line.ref.bz2')) as ref: - ref_str = ref.read().decode('utf-8') + with fs.open(resource('gvcfs/long_line.ref.bz2'), 'rb') as ref: + ref_str = bz2.open(ref).read().decode('utf-8') self.assertEqual(ref_str, data) def test_vcf_parser_golden_master__ex_GRCh37(self): @@ -421,62 +399,24 @@ def _test_vcf_parser_golden_master(self, vcf_path, rg): mt = hl.read_matrix_table(vcf_path + '.mt') self.assertTrue(mt._same(vcf)) - @fails_service_backend() - @fails_local_backend() - def test_import_multiple_vcfs(self): - _paths = ['gvcfs/HG00096.g.vcf.gz', 'gvcfs/HG00268.g.vcf.gz'] - paths = [resource(p) for p in _paths] - parts = [ - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 17821257, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 18708366, reference_genome='GRCh38')), - includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 18708367, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 19776611, reference_genome='GRCh38')), - includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 19776612, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 21144633, reference_genome='GRCh38')), - includes_end=True) - ] - int0 = hl.parse_locus_interval('[chr20:17821257-18708366]', reference_genome='GRCh38') - int1 = hl.parse_locus_interval('[chr20:18708367-19776611]', reference_genome='GRCh38') - hg00096, hg00268 = hl.import_gvcfs(paths, parts, reference_genome='GRCh38') - filt096 = hl.filter_intervals(hg00096, [int0]) - filt268 = hl.filter_intervals(hg00268, [int1]) - self.assertEqual(1, filt096.n_partitions()) - self.assertEqual(1, filt268.n_partitions()) - pos096 = set(filt096.locus.position.collect()) - pos268 = set(filt268.locus.position.collect()) - self.assertFalse(pos096 & pos268) - - @fails_service_backend() - @fails_local_backend() def test_combiner_works(self): - from hail.experimental.vcf_combiner.vcf_combiner import transform_one, combine_gvcfs + from hail.vds.combiner.combine import transform_gvcf, combine_variant_datasets _paths = ['gvcfs/HG00096.g.vcf.gz', 'gvcfs/HG00268.g.vcf.gz'] paths = [resource(p) for p in _paths] - parts = [ - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 17821257, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 18708366, reference_genome='GRCh38')), - includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 18708367, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 19776611, reference_genome='GRCh38')), - includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 19776612, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 21144633, reference_genome='GRCh38')), - includes_end=True) - ] - vcfs = [transform_one(mt.annotate_rows(info=mt.info.annotate( - MQ_DP=hl.missing(hl.tint32), - VarDP=hl.missing(hl.tint32), - QUALapprox=hl.missing(hl.tint32)))) - for mt in hl.import_gvcfs(paths, parts, reference_genome='GRCh38', - array_elements_required=False)] - comb = combine_gvcfs(vcfs) - self.assertEqual(len(parts), comb.n_partitions()) - comb._force_count_rows() + vdses = [] + for path in paths: + mt = hl.import_vcf(path, reference_genome='GRCh38', array_elements_required=False, force_bgz=True) + mt = transform_gvcf(mt.annotate_rows(info=mt.info.annotate( + MQ_DP=hl.missing(hl.tint32), + VarDP=hl.missing(hl.tint32), + QUALapprox=hl.missing(hl.tint32))), reference_entry_fields_to_keep=[]) + vdses.append(mt) + comb = combine_variant_datasets(vdses) + assert comb.reference_data._force_count_rows() == 458646 + assert comb.variant_data._force_count_rows() == 14346 def test_haploid_combiner_ok(self): - from hail.experimental.vcf_combiner.vcf_combiner import transform_gvcf + from hail.vds.combiner.combine import transform_gvcf # make a combiner table mt = hl.utils.range_matrix_table(2, 1) mt = mt.annotate_cols(s='S01') @@ -492,10 +432,12 @@ def test_haploid_combiner_ok(self): mt = mt.annotate_rows(info=hl.struct(END=mt.locus.position)) mt = mt.annotate_rows(rsid=hl.missing(hl.tstr)) mt = mt.drop('row_idx') - transform_gvcf(mt)._force_count() + vds = transform_gvcf(mt, []) + vds.reference_data._force_count_rows() + vds.variant_data._force_count_rows() def test_combiner_parse_as_annotations(self): - from hail.experimental.vcf_combiner.vcf_combiner import parse_as_fields + from hail.vds.combiner.combine import parse_as_fields infos = hl.array([ hl.struct( AS_QUALapprox="|1171|", diff --git a/hail/python/test/hail/vds/test_combiner.py b/hail/python/test/hail/vds/test_combiner.py index bd6d385624c..1b4e4726ff2 100644 --- a/hail/python/test/hail/vds/test_combiner.py +++ b/hail/python/test/hail/vds/test_combiner.py @@ -22,69 +22,27 @@ 'NA20796', 'HG00323', 'HG01384', 'NA18613', 'NA20802'] -@fails_local_backend -@fails_service_backend def test_combiner_works(): _paths = ['gvcfs/HG00096.g.vcf.gz', 'gvcfs/HG00268.g.vcf.gz'] paths = [resource(p) for p in _paths] parts = [ - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 17821257, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 18708366, reference_genome='GRCh38')), + hl.Interval(start=hl.Locus('chr20', 17821257, reference_genome='GRCh38'), + end=hl.Locus('chr20', 18708366, reference_genome='GRCh38'), includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 18708367, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 19776611, reference_genome='GRCh38')), + hl.Interval(start=hl.Locus('chr20', 18708367, reference_genome='GRCh38'), + end=hl.Locus('chr20', 19776611, reference_genome='GRCh38'), includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 19776612, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 21144633, reference_genome='GRCh38')), + hl.Interval(start=hl.Locus('chr20', 19776612, reference_genome='GRCh38'), + end=hl.Locus('chr20', 21144633, reference_genome='GRCh38'), includes_end=True) ] - vcfs = hl.import_gvcfs(paths, parts, reference_genome='GRCh38', array_elements_required=False) - entry_to_keep = defined_entry_fields(vcfs[0].filter_rows(hl.is_defined(vcfs[0].info.END)), 100_000) - {'GT', 'PGT', 'PL'} - vcfs = [transform_gvcf(mt.annotate_rows(info=mt.info.annotate( - MQ_DP=hl.missing(hl.tint32), - VarDP=hl.missing(hl.tint32), - QUALapprox=hl.missing(hl.tint32))), - reference_entry_fields_to_keep=entry_to_keep) - for mt in vcfs] - comb = combine_variant_datasets(vcfs) - assert len(parts) == comb.variant_data.n_partitions() - comb.variant_data._force_count_rows() - comb.reference_data._force_count_rows() - - -@fails_local_backend -@fails_service_backend -@test_timeout(12 * 60) -def test_vcf_vds_combiner_equivalence(): - import hail.experimental.vcf_combiner.vcf_combiner as vcf - import hail.vds.combiner as vds - _paths = ['gvcfs/HG00096.g.vcf.gz', 'gvcfs/HG00268.g.vcf.gz'] - paths = [resource(p) for p in _paths] - parts = [ - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 17821257, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 18708366, reference_genome='GRCh38')), - includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 18708367, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 19776611, reference_genome='GRCh38')), - includes_end=True), - hl.Interval(start=hl.Struct(locus=hl.Locus('chr20', 19776612, reference_genome='GRCh38')), - end=hl.Struct(locus=hl.Locus('chr20', 21144633, reference_genome='GRCh38')), - includes_end=True) - ] - vcfs = [mt.annotate_rows(info=mt.info.annotate( - MQ_DP=hl.missing(hl.tint32), - VarDP=hl.missing(hl.tint32), - QUALapprox=hl.missing(hl.tint32))) - for mt in hl.import_gvcfs(paths, parts, reference_genome='GRCh38', - array_elements_required=False)] - entry_to_keep = defined_entry_fields(vcfs[0].filter_rows(hl.is_defined(vcfs[0].info.END)), 100_000) - {'GT', 'PGT', 'PL'} - vds = vds.combine_variant_datasets([vds.transform_gvcf(mt, reference_entry_fields_to_keep=entry_to_keep) for mt in vcfs]) - vds.variant_data = vds.variant_data.drop('RGQ') - smt = vcf.combine_gvcfs([vcf.transform_gvcf(mt) for mt in vcfs]).drop('RGQ') - vds_from_smt = hl.vds.VariantDataset.from_merged_representation(smt, ref_block_fields=list(vds.reference_data.entry.drop('END'))) - - assert vds.variant_data._same(vds_from_smt.variant_data, reorder_fields=True) - assert vds.reference_data._same(vds_from_smt.reference_data, reorder_fields=True) + with hl.TemporaryDirectory() as tmpdir: + out = os.path.join(tmpdir, 'out.vds') + hl.vds.new_combiner(temp_path=tmpdir, output_path=out, gvcf_paths=paths, intervals=parts, reference_genome='GRCh38').run() + comb = hl.vds.read_vds(out) + assert len(parts) == comb.variant_data.n_partitions() + comb.variant_data._force_count_rows() + comb.reference_data._force_count_rows() def test_combiner_plan_round_trip_serialization(): @@ -151,11 +109,8 @@ def test_move_load_combiner_plan(): assert plan == plan_loaded -@fails_local_backend -@fails_service_backend -@test_timeout(5 * 60) +@test_timeout(10 * 60) def test_combiner_run(): - tmpdir = new_temp_file() samples = all_samples[:5] @@ -188,8 +143,6 @@ def test_combiner_run(): assert hl.vds.read_vds(final_path_1)._same(hl.vds.read_vds(final_path_2)) -@fails_service_backend() -@fails_local_backend() def test_combiner_manual_filtration(): sample_names = all_samples[:2] paths = [os.path.join(resource('gvcfs'), '1kg_chr22', f'{s}.hg38.g.vcf.gz') for s in sample_names] @@ -211,8 +164,7 @@ def test_combiner_manual_filtration(): assert list(vds.reference_data.entry) == ['END', 'GQ'] -@fails_service_backend() -@fails_local_backend() +@test_timeout(10 * 60) def test_ref_block_max_len_propagates_in_combiner(): gvcfs = ['NA21123.hg38.g.vcf.gz', 'NA21099.hg38.g.vcf.gz', 'NA19747.hg38.g.vcf.gz'] with hl.TemporaryDirectory() as tmpdir: diff --git a/hail/python/test/hail/vds/test_vds.py b/hail/python/test/hail/vds/test_vds.py index 4912f42b9a6..5b64c4521db 100644 --- a/hail/python/test/hail/vds/test_vds.py +++ b/hail/python/test/hail/vds/test_vds.py @@ -55,37 +55,6 @@ def test_multi_write(): assert hl.vds.read_vds(path1)._same(vds1) assert hl.vds.read_vds(path2)._same(vds2) -@fails_local_backend -@fails_service_backend -def test_conversion_equivalence(): - gvcfs = [os.path.join(resource('gvcfs'), '1kg_chr22', path) for path in ['HG00187.hg38.g.vcf.gz', - 'HG00190.hg38.g.vcf.gz', - 'HG00308.hg38.g.vcf.gz', - 'HG00313.hg38.g.vcf.gz', - 'HG00320.hg38.g.vcf.gz']] - - tmpdir = new_temp_file() - mt_path = new_temp_file() - vds_path = new_temp_file() - - hl.experimental.run_combiner(gvcfs, mt_path, tmpdir, use_exome_default_intervals=True, reference_genome='GRCh38', - overwrite=True, intervals=[hl.eval(hl.parse_locus_interval('chr22', 'GRCh38'))], - key_by_locus_and_alleles=True) - - svcr = hl.read_matrix_table(mt_path) - - vds = hl.vds.VariantDataset.from_merged_representation(svcr).checkpoint(vds_path) - ref = vds.reference_data - var = vds.variant_data - - assert svcr.aggregate_entries(hl.agg.count_where(hl.is_defined(svcr.END))) == ref.aggregate_entries(hl.agg.count()) - assert svcr.aggregate_entries(hl.agg.count()) == ref.aggregate_entries(hl.agg.count()) + var.aggregate_entries( - hl.agg.count()) - - svcr_readback = hl.vds.to_merged_sparse_mt(vds, ref_allele_function=lambda ht: svcr.key_rows_by('locus').index_rows(ht.locus).alleles[0]) - - assert svcr._same(svcr_readback, reorder_fields=True) - def test_sampleqc_old_new_equivalence(): vds = hl.vds.read_vds(os.path.join(resource('vds'), '1kg_chr22_5_samples.vds')) diff --git a/hail/src/main/scala/is/hail/HailContext.scala b/hail/src/main/scala/is/hail/HailContext.scala index 719edb2c2f9..96347a7230a 100644 --- a/hail/src/main/scala/is/hail/HailContext.scala +++ b/hail/src/main/scala/is/hail/HailContext.scala @@ -136,10 +136,6 @@ object HailContext { theContext = null } - def pyRemoveIrVector(id: Int) { - get.irVectors.remove(id) - } - def readPartitions[T: ClassTag]( fs: FS, path: String, @@ -176,20 +172,6 @@ class HailContext private( var checkRVDKeys: Boolean = false - private var nextVectorId: Int = 0 - val irVectors: mutable.Map[Int, Array[_ <: BaseIR]] = mutable.Map.empty[Int, Array[_ <: BaseIR]] - - def addIrVector(irArray: Array[_ <: BaseIR]): Int = { - val typ = irArray.head.typ - irArray.foreach { ir => - if (ir.typ != typ) - fatal("all ir vector items must have the same type") - } - irVectors(nextVectorId) = irArray - nextVectorId += 1 - nextVectorId - 1 - } - def version: String = is.hail.HAIL_PRETTY_VERSION private[this] def fileAndLineCounts( diff --git a/hail/src/main/scala/is/hail/asm4s/CodeBuilder.scala b/hail/src/main/scala/is/hail/asm4s/CodeBuilder.scala index e8581b96dce..950fef6fa34 100644 --- a/hail/src/main/scala/is/hail/asm4s/CodeBuilder.scala +++ b/hail/src/main/scala/is/hail/asm4s/CodeBuilder.scala @@ -1,6 +1,7 @@ package is.hail.asm4s import is.hail.lir +import is.hail.asm4s._ abstract class SettableBuilder { def newSettable[T](name: String)(implicit tti: TypeInfo[T]): Settable[T] @@ -56,6 +57,9 @@ trait CodeBuilderLike { def fieldBuilder: SettableBuilder = mb.fieldBuilder def +=(c: Code[Unit]): Unit = append(c) + def updateArray[T](array: Code[Array[T]], index: Code[Int], value: Code[T])(implicit tti: TypeInfo[T]): Unit = { + append(array.update(index, value)) + } def memoize[T: TypeInfo](v: Code[T], optionalName: String = ""): Value[T] = v match { case b: ConstCodeBoolean => coerce[T](b.b) diff --git a/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala b/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala index 394333060a6..23214020a1e 100644 --- a/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala +++ b/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala @@ -26,7 +26,6 @@ import scala.reflect.ClassTag import scala.collection.JavaConverters._ import java.io.{Closeable, PrintWriter} import is.hail.io.plink.LoadPlink -import is.hail.io.vcf.VCFsReader import is.hail.linalg.{BlockMatrix, RowMatrix} import is.hail.rvd.RVD import is.hail.stats.LinearMixedModel @@ -550,48 +549,6 @@ class SparkBackend( } } - def pyImportVCFs( - files: java.util.List[String], - callFields: java.util.List[String], - entryFloatTypeName: String, - rg: String, - contigRecoding: java.util.Map[String, String], - arrayElementsRequired: Boolean, - skipInvalidLoci: Boolean, - partitionsJSON: String, - partitionsTypeStr: String, - filter: String, - find: String, - replace: String, - externalSampleIds: java.util.List[java.util.List[String]], - externalHeader: String - ): String = { - ExecutionTimer.logTime("SparkBackend.pyImportVCFs") { timer => - withExecuteContext(timer) { ctx => - val reader = new VCFsReader(ctx, - files.asScala.toArray, - callFields.asScala.toSet, - entryFloatTypeName, - Option(rg), - Option(contigRecoding).map(_.asScala.toMap).getOrElse(Map.empty[String, String]), - arrayElementsRequired, - skipInvalidLoci, - TextInputFilterAndReplace(Option(find), Option(filter), Option(replace)), - partitionsJSON, partitionsTypeStr, - Option(externalSampleIds).map(_.asScala.map(_.asScala.toArray).toArray), - Option(externalHeader)) - - val irs = reader.read(ctx) - val id = HailContext.get.addIrVector(irs) - val out = JObject( - "vector_ir_id" -> JInt(id), - "length" -> JInt(irs.length), - "type" -> reader.typ.pyJson) - JsonMethods.compact(out) - } - } - } - def pyReadMultipleMatrixTables(jsonQuery: String): java.util.List[MatrixIR] = { log.info("pyReadMultipleMatrixTables: got query") val kvs = JsonMethods.parse(jsonQuery) match { diff --git a/hail/src/main/scala/is/hail/expr/ir/Binds.scala b/hail/src/main/scala/is/hail/expr/ir/Binds.scala index 095da71c979..fe961351ff2 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Binds.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Binds.scala @@ -25,6 +25,16 @@ object Bindings { curVals -> TArray(eltType)) else empty + case StreamZipJoinProducers(contexts, ctxName, makeProducer, key, curKey, curVals, _) => + val contextType = TIterable.elementType(contexts.typ) + val eltType = tcoerce[TStruct](tcoerce[TStream](makeProducer.typ).elementType) + if (i == 1) + Array(ctxName -> contextType) + else if (i == 2) + Array(curKey -> eltType.typeAfterSelectNames(key), + curVals -> TArray(eltType)) + else + empty case StreamFor(a, name, _) => if (i == 1) Array(name -> tcoerce[TStream](a.typ).elementType) else empty case StreamFlatMap(a, name, _) => if (i == 1) Array(name -> tcoerce[TStream](a.typ).elementType) else empty case StreamFilter(a, name, _) => if (i == 1) Array(name -> tcoerce[TStream](a.typ).elementType) else empty diff --git a/hail/src/main/scala/is/hail/expr/ir/Children.scala b/hail/src/main/scala/is/hail/expr/ir/Children.scala index 146ef135f7e..4d973055cfc 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Children.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Children.scala @@ -118,6 +118,8 @@ object Children { as :+ body case StreamZipJoin(as, _, _, _, joinF) => as :+ joinF + case StreamZipJoinProducers(contexts, _, makeProducer, _, _, _, joinF) => + Array(contexts, makeProducer, joinF) case StreamMultiMerge(as, _) => as case StreamFilter(a, name, cond) => diff --git a/hail/src/main/scala/is/hail/expr/ir/Copy.scala b/hail/src/main/scala/is/hail/expr/ir/Copy.scala index ba68a1f4786..76fb399421f 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Copy.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Copy.scala @@ -200,6 +200,10 @@ object Copy { case StreamZipJoin(as, key, curKey, curVals, _) => assert(newChildren.length == as.length + 1) StreamZipJoin(newChildren.init.asInstanceOf[IndexedSeq[IR]], key, curKey, curVals, newChildren(as.length).asInstanceOf[IR]) + case StreamZipJoinProducers(_, ctxName, _, key, curKey, curVals, _) => + assert(newChildren.length == 3) + StreamZipJoinProducers(newChildren(0).asInstanceOf[IR], ctxName, newChildren(1).asInstanceOf[IR], + key, curKey, curVals, newChildren(2).asInstanceOf[IR]) case StreamMultiMerge(as, key) => assert(newChildren.length == as.length) StreamMultiMerge(newChildren.asInstanceOf[IndexedSeq[IR]], key) diff --git a/hail/src/main/scala/is/hail/expr/ir/EmitCodeBuilder.scala b/hail/src/main/scala/is/hail/expr/ir/EmitCodeBuilder.scala index 85e107e1702..9216eef3e19 100644 --- a/hail/src/main/scala/is/hail/expr/ir/EmitCodeBuilder.scala +++ b/hail/src/main/scala/is/hail/expr/ir/EmitCodeBuilder.scala @@ -44,8 +44,6 @@ class EmitCodeBuilder(val emb: EmitMethodBuilder[_], var code: Code[Unit]) exten def mb: MethodBuilder[_] = emb.mb - val stateManager: Value[HailStateManager] = null - def uncheckedAppend(c: Code[Unit]): Unit = { code = Code(code, c) } diff --git a/hail/src/main/scala/is/hail/expr/ir/Exists.scala b/hail/src/main/scala/is/hail/expr/ir/Exists.scala index a35f705c34c..c53348734eb 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Exists.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Exists.scala @@ -93,7 +93,7 @@ object ContainsAggIntermediate { object AggIsCommutative { def apply(op: AggOp): Boolean = op match { - case Take() | Collect() | PrevNonnull() | TakeBy(_) | ReservoirSample() => false + case Take() | Collect() | PrevNonnull() | TakeBy(_) | ReservoirSample() | Fold() => false case _ => true } } diff --git a/hail/src/main/scala/is/hail/expr/ir/GenericLines.scala b/hail/src/main/scala/is/hail/expr/ir/GenericLines.scala index d49b491922a..e5b469f49cd 100644 --- a/hail/src/main/scala/is/hail/expr/ir/GenericLines.scala +++ b/hail/src/main/scala/is/hail/expr/ir/GenericLines.scala @@ -309,7 +309,7 @@ object GenericLines { GenericLines.read(fs, contexts, gzAsBGZ, filePerPartition) } - def readTabix(fs: FS, fileStatus: FileStatus, contigMapping: Map[String, String], partitions: IndexedSeq[Interval]): GenericLines = { + def readTabix(fs: FS, path: String, contigMapping: Map[String, String], partitions: IndexedSeq[Interval]): GenericLines = { val reverseContigMapping: Map[String, String] = contigMapping.toArray .groupBy(_._2) @@ -324,7 +324,7 @@ object GenericLines { val start = interval.start.asInstanceOf[Row].getAs[Locus](0) val end = interval.end.asInstanceOf[Row].getAs[Locus](0) val contig = reverseContigMapping.getOrElse(start.contig, start.contig) - Row(i, fileStatus.getPath, contig, start.position, end.position) + Row(i, path, contig, start.position, end.position) } val body: (FS, Any) => CloseableIterator[GenericLine] = { (fs: FS, context: Any) => val contextRow = context.asInstanceOf[Row] diff --git a/hail/src/main/scala/is/hail/expr/ir/IR.scala b/hail/src/main/scala/is/hail/expr/ir/IR.scala index 013edc28131..7f57a6bb354 100644 --- a/hail/src/main/scala/is/hail/expr/ir/IR.scala +++ b/hail/src/main/scala/is/hail/expr/ir/IR.scala @@ -10,6 +10,7 @@ import is.hail.expr.ir.lowering.TableStageDependency import is.hail.expr.ir.streams.StreamProducer import is.hail.io.avro.{AvroPartitionReader, AvroSchemaSerializer} import is.hail.io.bgen.BgenPartitionReader +import is.hail.io.vcf.{GVCFPartitionReader, VCFHeaderInfo} import is.hail.io.{AbstractTypedCodecSpec, BufferSpec, TypedCodecSpec} import is.hail.rvd.RVDSpecMaker import is.hail.types.encoded._ @@ -20,6 +21,7 @@ import is.hail.types.physical.stypes.interfaces._ import is.hail.types.virtual._ import is.hail.types.{RIterable, RStruct, TypeWithRequiredness, tcoerce} import is.hail.utils.{FastIndexedSeq, _} +import org.json4s.JsonAST.{JNothing, JString} import org.json4s.{DefaultFormats, Extraction, Formats, JValue, ShortTypeHints} import java.io.OutputStream @@ -356,6 +358,11 @@ final case class StreamMultiMerge(as: IndexedSeq[IR], key: IndexedSeq[String]) e override def typ: TStream = tcoerce[TStream](super.typ) } +final case class StreamZipJoinProducers(contexts: IR, ctxName: String, makeProducer: IR, + key: IndexedSeq[String], curKey: String, curVals: String, joinF: IR) extends IR { + override def typ: TStream = tcoerce[TStream](super.typ) +} + /** * The StreamZipJoin node assumes that input streams have distinct keys. If input streams * do not have distinct keys, the key that is included in the result is undefined, but @@ -783,6 +790,9 @@ object PartitionReader { classOf[PartitionZippedNativeReader], classOf[PartitionZippedIndexedNativeReader], classOf[BgenPartitionReader], + classOf[GVCFPartitionReader], + classOf[TextInputFilterAndReplace], + classOf[VCFHeaderInfo], classOf[AbstractTypedCodecSpec], classOf[TypedCodecSpec], classOf[AvroPartitionReader]), @@ -800,6 +810,22 @@ object PartitionReader { val path = (jv \ "path").extract[String] val spec = TableNativeReader.read(ctx.fs, path, None).spec PartitionNativeIntervalReader(ctx.stateManager, path, spec, (jv \ "uidFieldName").extract[String]) + case "GVCFPartitionReader" => + val header = VCFHeaderInfo.fromJSON((jv \ "header")) + val callFields = (jv \ "callFields").extract[Set[String]] + val entryFloatType = IRParser.parseType((jv \ "entryFloatType").extract[String]) + val arrayElementsRequired = (jv \ "arrayElementsRequired").extract[Boolean] + val rg = (jv \ "rg") match { + case JString(s) => Some(s) + case JNothing => None + } + val contigRecoding = (jv \ "contigRecoding").extract[Map[String, String]] + val skipInvalidLoci = (jv \ "skipInvalidLoci").extract[Boolean] + val filterAndReplace = (jv \ "filterAndReplace").extract[TextInputFilterAndReplace] + val entriesFieldName = (jv \ "entriesFieldName").extract[String] + val uidFieldName = (jv \ "uidFieldName").extract[String] + GVCFPartitionReader(header, callFields, entryFloatType, arrayElementsRequired, rg, contigRecoding, + skipInvalidLoci, filterAndReplace, entriesFieldName, uidFieldName) case _ => jv.extract[PartitionReader] } } diff --git a/hail/src/main/scala/is/hail/expr/ir/InferType.scala b/hail/src/main/scala/is/hail/expr/ir/InferType.scala index d0e789d15cb..9dadea3f476 100644 --- a/hail/src/main/scala/is/hail/expr/ir/InferType.scala +++ b/hail/src/main/scala/is/hail/expr/ir/InferType.scala @@ -136,6 +136,8 @@ object InferType { TStream(body.typ) case StreamZipJoin(_, _, _, _, joinF) => TStream(joinF.typ) + case StreamZipJoinProducers(_, _, _, _, _, _, joinF) => + TStream(joinF.typ) case StreamMultiMerge(as, _) => TStream(tcoerce[TStream](as.head.typ).elementType) case StreamFilter(a, name, cond) => diff --git a/hail/src/main/scala/is/hail/expr/ir/Interpretable.scala b/hail/src/main/scala/is/hail/expr/ir/Interpretable.scala index caf1820ce20..3024703c790 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Interpretable.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Interpretable.scala @@ -41,6 +41,7 @@ object Interpretable { _: ReadValue | _: WriteValue | _: NDArrayWrite | + _: StreamZipJoinProducers | _: RNGStateLiteral => false case x: ApplyIR => !Exists(x.body, { diff --git a/hail/src/main/scala/is/hail/expr/ir/MatrixIR.scala b/hail/src/main/scala/is/hail/expr/ir/MatrixIR.scala index e2514bd0e38..05648369550 100644 --- a/hail/src/main/scala/is/hail/expr/ir/MatrixIR.scala +++ b/hail/src/main/scala/is/hail/expr/ir/MatrixIR.scala @@ -108,7 +108,7 @@ trait MatrixReader { def colUIDType: Type - val fullMatrixType: MatrixType = { + lazy val fullMatrixType: MatrixType = { val mt = fullMatrixTypeWithoutUIDs val rowType = mt.rowType val newRowType = if (rowType.hasField(rowUIDFieldName)) diff --git a/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala b/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala index 2754e0b645e..ee1b92cd449 100644 --- a/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala +++ b/hail/src/main/scala/is/hail/expr/ir/NestingDepth.scala @@ -60,6 +60,13 @@ object NestingDepth { case StreamZip(as, _, body, _, _) => as.foreach(computeIR(_, depth)) computeIR(body, depth.incrementEval) + case StreamZipJoin(as, _, _, _, joinF) => + as.foreach(computeIR(_, depth)) + computeIR(joinF, depth.incrementEval) + case StreamZipJoinProducers(contexts, _, makeProducer, _, _, _, joinF) => + computeIR(contexts, depth) + computeIR(makeProducer, depth.incrementEval) + computeIR(joinF, depth.incrementEval) case StreamFor(a, valueName, body) => computeIR(a, depth) computeIR(body, depth.incrementEval) diff --git a/hail/src/main/scala/is/hail/expr/ir/NormalizeNames.scala b/hail/src/main/scala/is/hail/expr/ir/NormalizeNames.scala index dd6d4e21358..42843cc6430 100644 --- a/hail/src/main/scala/is/hail/expr/ir/NormalizeNames.scala +++ b/hail/src/main/scala/is/hail/expr/ir/NormalizeNames.scala @@ -98,6 +98,15 @@ class NormalizeNames(normFunction: Int => String, allowFreeVariables: Boolean = newAs <- as.mapRecur(normalize(_)) newJoinF <- normalize(joinF, env.bindEval(curKey -> newCurKey, curVals -> newCurVals)) } yield StreamZipJoin(newAs, key, newCurKey, newCurVals, newJoinF) + case StreamZipJoinProducers(contexts, ctxName, makeProducer, key, curKey, curVals, joinF) => + val newCtxName = gen() + val newCurKey = gen() + val newCurVals = gen() + for { + newCtxs <- normalize(contexts) + newMakeProducer <- normalize(makeProducer, env.bindEval(ctxName -> newCtxName)) + newJoinF <- normalize(joinF, env.bindEval(curKey -> newCurKey, curVals -> newCurVals)) + } yield StreamZipJoinProducers(newCtxs, newCtxName, newMakeProducer, key, newCurKey, newCurVals, newJoinF) case StreamFilter(a, name, body) => val newName = gen() for { diff --git a/hail/src/main/scala/is/hail/expr/ir/Parser.scala b/hail/src/main/scala/is/hail/expr/ir/Parser.scala index 9a6fb167bb8..9e9f289025f 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Parser.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Parser.scala @@ -1133,6 +1133,19 @@ object IRParser { as <- names.mapRecur(_ => ir_value_expr(env)(it)) body <- ir_value_expr(env.bindEval(names.zip(as.map(a => tcoerce[TStream](a.typ).elementType)): _*))(it) } yield StreamZip(as, names, body, behavior, errorID) + case "StreamZipJoinProducers" => + val key = identifiers(it) + val ctxName = identifier(it) + val curKey = identifier(it) + val curVals = identifier(it) + for { + ctxs <- ir_value_expr(env)(it) + makeProducer <- ir_value_expr(env.bindEval(ctxName, TIterable.elementType(ctxs.typ)))(it) + body <- { + val structType = TIterable.elementType(makeProducer.typ).asInstanceOf[TStruct] + ir_value_expr(env.bindEval((curKey, structType.typeAfterSelectNames(key)), (curVals, TArray(structType))))(it) + } + } yield StreamZipJoinProducers(ctxs, ctxName, makeProducer, key, curKey, curVals, body) case "StreamZipJoin" => val nStreams = int32_literal(it) val key = identifiers(it) @@ -1992,10 +2005,6 @@ object IRParser { case "JavaMatrix" => val name = identifier(it) done(env.irMap(name).asInstanceOf[MatrixIR]) - case "JavaMatrixVectorRef" => - val id = int32_literal(it) - val idx = int32_literal(it) - done(HailContext.get.irVectors(id)(idx).asInstanceOf[MatrixIR]) } } diff --git a/hail/src/main/scala/is/hail/expr/ir/Pretty.scala b/hail/src/main/scala/is/hail/expr/ir/Pretty.scala index 44e2d8e2cda..b00415defd6 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Pretty.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Pretty.scala @@ -222,6 +222,8 @@ class Pretty(width: Int, ribbonWidth: Int, elideLiterals: Boolean, maxLen: Int, }, prettyIdentifiers(names)) case StreamZipJoin(streams, key, curKey, curVals, _) if !elideBindings => FastSeq(streams.length.toString, prettyIdentifiers(key), prettyIdentifier(curKey), prettyIdentifier(curVals)) + case StreamZipJoinProducers(_, ctxName, _, key, curKey, curVals, _) if !elideBindings => + FastSeq(prettyIdentifiers(key), prettyIdentifier(ctxName), prettyIdentifier(curKey), prettyIdentifier(curVals)) case StreamMultiMerge(_, key) => single(prettyIdentifiers(key)) case StreamFilter(_, name, _) if !elideBindings => single(prettyIdentifier(name)) case StreamTakeWhile(_, name, _) if !elideBindings => single(prettyIdentifier(name)) diff --git a/hail/src/main/scala/is/hail/expr/ir/PruneDeadFields.scala b/hail/src/main/scala/is/hail/expr/ir/PruneDeadFields.scala index 617065c3d15..cc47db672ff 100644 --- a/hail/src/main/scala/is/hail/expr/ir/PruneDeadFields.scala +++ b/hail/src/main/scala/is/hail/expr/ir/PruneDeadFields.scala @@ -1134,6 +1134,17 @@ object PruneDeadFields { uses(curVals, bodyEnv.eval).map(TIterable.elementType) :+ selectKey(eltType, key) ) unifyEnvsSeq(as.map(memoizeValueIR(ctx, _, TStream(childRequestedEltType), memo))) + case StreamZipJoinProducers(contexts, ctxName, makeProducer, key, curKey, curVals, joinF) => + val baseEltType = tcoerce[TStruct](TIterable.elementType(makeProducer.typ)) + val requestedEltType = tcoerce[TStream](requestedType).elementType + val bodyEnv = memoizeValueIR(ctx, joinF, requestedEltType, memo) + val producerRequestedEltType = unifySeq( + baseEltType, + uses(curVals, bodyEnv.eval).map(TIterable.elementType) :+ selectKey(baseEltType, key) + ) + val producerEnv = memoizeValueIR(ctx, makeProducer, TStream(producerRequestedEltType), memo) + val ctxEnv = memoizeValueIR(ctx, contexts, TArray(unifySeq(TIterable.elementType(contexts.typ), uses(ctxName, producerEnv.eval))), memo) + unifyEnvsSeq(Array(bodyEnv, producerEnv, ctxEnv)) case StreamMultiMerge(as, key) => val eltType = tcoerce[TStruct](tcoerce[TStream](as.head.typ).elementType) val requestedEltType = tcoerce[TStream](requestedType).elementType @@ -1926,6 +1937,16 @@ object PruneDeadFields { env.bindEval(curKey -> selectKey(newEltType, key), curVals -> TArray(newEltType)), memo) StreamZipJoin(newAs, key, curKey, curVals, newJoinF) + case StreamZipJoinProducers(contexts, ctxName, makeProducer, key, curKey, curVals, joinF) => + val newContexts = rebuildIR(ctx, contexts, env, memo) + val newCtxType = TIterable.elementType(newContexts.typ) + val newMakeProducer = rebuildIR(ctx, makeProducer, env.bindEval(ctxName, newCtxType), memo) + val newEltType = TIterable.elementType(newMakeProducer.typ).asInstanceOf[TStruct] + val newJoinF = rebuildIR(ctx, + joinF, + env.bindEval(curKey -> selectKey(newEltType, key), curVals -> TArray(newEltType)), + memo) + StreamZipJoinProducers(newContexts, ctxName, newMakeProducer,key, curKey, curVals, newJoinF) case StreamMultiMerge(as, key) => val eltType = tcoerce[TStruct](tcoerce[TStream](as.head.typ).elementType) val requestedEltType = tcoerce[TStream](requestedType).elementType diff --git a/hail/src/main/scala/is/hail/expr/ir/Requiredness.scala b/hail/src/main/scala/is/hail/expr/ir/Requiredness.scala index 371f0b8412d..97803dd82c7 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Requiredness.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Requiredness.scala @@ -213,6 +213,29 @@ class Requiredness(val usesAndDefs: UsesAndDefs, ctx: ExecuteContext) { uses.foreach { u => defs.bind(u, valTypes) } as.foreach { a => dependents.getOrElseUpdate(a, mutable.Set[RefEquality[BaseIR]]()) ++= uses } } + case StreamZipJoinProducers(contexts, ctxName, makeProducer, key, curKey, curVals, _) => + val ctxType = tcoerce[RIterable](lookup(contexts)).elementType + if (refMap.contains(ctxName)) { + val uses = refMap(ctxName) + uses.foreach { u => defs.bind(u, Array(ctxType)) } + dependents.getOrElseUpdate(contexts, mutable.Set[RefEquality[BaseIR]]()) ++= uses + } + + val producerElementType = tcoerce[RStruct](tcoerce[RIterable](lookup(makeProducer)).elementType) + if (refMap.contains(curKey)) { + val uses = refMap(curKey) + val keyType = RStruct.fromNamesAndTypes(key.map(k => k -> producerElementType.fieldType(k))) + uses.foreach { u => defs.bind(u, Array(keyType)) } + dependents.getOrElseUpdate(makeProducer, mutable.Set[RefEquality[BaseIR]]()) ++= uses + } + if (refMap.contains(curVals)) { + val uses = refMap(curVals) + val optional = producerElementType.copy(producerElementType.children) + optional.union(false) + uses.foreach { u => defs.bind(u, Array(RIterable(optional))) } + dependents.getOrElseUpdate(makeProducer, mutable.Set[RefEquality[BaseIR]]()) ++= uses + } + case StreamFilter(a, name, cond) => addElementBinding(name, a) case StreamTakeWhile(a, name, cond) => addElementBinding(name, a) case StreamDropWhile(a, name, cond) => addElementBinding(name, a) @@ -584,6 +607,10 @@ class Requiredness(val usesAndDefs: UsesAndDefs, ctx: ExecuteContext) { requiredness.union(as.forall(lookup(_).required)) val eltType = tcoerce[RIterable](requiredness).elementType eltType.unionFrom(lookup(joinF)) + case StreamZipJoinProducers(contexts, ctxName, makeProducer, _, curKey, curVals, joinF) => + requiredness.union(lookup(contexts).required) + val eltType = tcoerce[RIterable](requiredness).elementType + eltType.unionFrom(lookup(joinF)) case StreamMultiMerge(as, _) => requiredness.union(as.forall(lookup(_).required)) val elt = tcoerce[RStruct](tcoerce[RIterable](requiredness).elementType) diff --git a/hail/src/main/scala/is/hail/expr/ir/TypeCheck.scala b/hail/src/main/scala/is/hail/expr/ir/TypeCheck.scala index 66addb26218..e06d3b2cd2b 100644 --- a/hail/src/main/scala/is/hail/expr/ir/TypeCheck.scala +++ b/hail/src/main/scala/is/hail/expr/ir/TypeCheck.scala @@ -342,6 +342,12 @@ object TypeCheck { val eltType = tcoerce[TStruct](streamType.elementType) assert(key.forall(eltType.hasField)) assert(x.typ.elementType == joinF.typ) + case x@StreamZipJoinProducers(contexts, ctxName, makeProducer, key, curKey, curVals, joinF) => + assert(contexts.typ.isInstanceOf[TArray]) + val streamType = tcoerce[TStream](makeProducer.typ) + val eltType = tcoerce[TStruct](streamType.elementType) + assert(key.forall(eltType.hasField)) + assert(x.typ.elementType == joinF.typ) case x@StreamMultiMerge(as, key) => val streamType = tcoerce[TStream](as.head.typ) assert(as.forall(_.typ == streamType)) diff --git a/hail/src/main/scala/is/hail/expr/ir/functions/UtilFunctions.scala b/hail/src/main/scala/is/hail/expr/ir/functions/UtilFunctions.scala index 0d4b5e3cb38..62bcf3c99ac 100644 --- a/hail/src/main/scala/is/hail/expr/ir/functions/UtilFunctions.scala +++ b/hail/src/main/scala/is/hail/expr/ir/functions/UtilFunctions.scala @@ -1,9 +1,13 @@ package is.hail.expr.ir.functions -import java.util.IllegalFormatConversionException +import is.hail.annotations.Region +import java.util.IllegalFormatConversionException import is.hail.asm4s.{coerce => _, _} +import is.hail.backend.HailStateManager import is.hail.expr.ir._ +import is.hail.io.fs.FS +import is.hail.io.vcf.{LoadVCF, VCFHeaderInfo} import is.hail.types.physical.stypes._ import is.hail.types.physical.stypes.concrete.SJavaString import is.hail.types.physical.stypes.interfaces._ @@ -397,5 +401,36 @@ object UtilFunctions extends RegistryFunctions { IEmitCode(cb, ((M >> w) & 1).cne(0), primitive(cb.memoize(w.cne(0)))) } } + + registerIEmitCode4("getVCFHeader", TString, TString, TString, TString, + VCFHeaderInfo.headerType, (_, fileET, _, _, _) => EmitType(VCFHeaderInfo.headerTypePType.sType, fileET.required)) { + case (cb, r, rt, errID, file, filter, find, replace) => + file.toI(cb).map(cb) { case filePath: SStringValue => + val filterVar = cb.newLocal[String]("filterVar") + val findVar = cb.newLocal[String]("findVar") + val replaceVar = cb.newLocal[String]("replaceVar") + filter.toI(cb).consume(cb, { + cb.assign(filterVar, Code._null) + }, { filt => + cb.assign(filterVar, filt.asString.loadString(cb)) + }) + find.toI(cb).consume(cb, { + cb.assign(findVar, Code._null) + }, { find => + cb.assign(findVar, find.asString.loadString(cb)) + }) + replace.toI(cb).consume(cb, { + cb.assign(replaceVar, Code._null) + }, { replace => + cb.assign(replaceVar, replace.asString.loadString(cb)) + }) + val hd = Code.invokeScalaObject5[FS, String, String, String, String, VCFHeaderInfo]( + LoadVCF.getClass, "getVCFHeaderInfo", cb.emb.getFS, + filePath.loadString(cb), filterVar, findVar, replaceVar) + val addr = cb.memoize(hd.invoke[HailStateManager, Region, Boolean, Long]("writeToRegion", + cb.emb.getObject(cb.emb.ecb.ctx.stateManager), r, const(false))) + VCFHeaderInfo.headerTypePType.loadCheapSCode(cb, addr) + } + } } } diff --git a/hail/src/main/scala/is/hail/expr/ir/streams/EmitStream.scala b/hail/src/main/scala/is/hail/expr/ir/streams/EmitStream.scala index b8010a6cf37..715abe366cf 100644 --- a/hail/src/main/scala/is/hail/expr/ir/streams/EmitStream.scala +++ b/hail/src/main/scala/is/hail/expr/ir/streams/EmitStream.scala @@ -15,7 +15,7 @@ import is.hail.types.physical.stypes.primitives.{SFloat64Value, SInt32Value} import is.hail.types.physical.stypes.{EmitType, SSettable} import is.hail.types.physical.{PCanonicalArray, PCanonicalBinary, PCanonicalStruct, PType} import is.hail.types.virtual._ -import is.hail.types.{TypeWithRequiredness, VirtualTypeWithReq} +import is.hail.types.{RIterable, TypeWithRequiredness, VirtualTypeWithReq} import is.hail.utils._ import is.hail.variant.Locus import org.objectweb.asm.Opcodes._ @@ -2741,6 +2741,241 @@ object EmitStream { SStreamValue(producer) } + case x@StreamZipJoinProducers(contexts, ctxName, makeProducer, key, keyRef, valsRef, joinIR) => + emit(contexts, cb).map(cb) { case contextsArray: SIndexableValue => + val nStreams = cb.memoizeField(contextsArray.loadLength()) + val iterArray = cb.memoizeField(Code.newArray[NoBoxLongIterator](nStreams), "iterArray") + val idx = cb.newLocal[Int]("i", 0) + val eltType = VirtualTypeWithReq(TIterable.elementType(makeProducer.typ), + emitter.ctx.req.lookup(makeProducer).asInstanceOf[RIterable].elementType).canonicalPType + .asInstanceOf[PCanonicalStruct] + .setRequired(false) + var streamRequiresMemoryManagement = false + cb.whileLoop(idx < nStreams, { + val iter = produceIterator(makeProducer, + eltType, + cb, + outerRegion, + env.bind(ctxName, cb.memoize(contextsArray.loadElement(cb, idx)))) + .get(cb, "streams in zipJoinProducers cannot be missing") + .asInstanceOf[SStreamConcrete] + streamRequiresMemoryManagement = iter.st.requiresMemoryManagement + cb += iterArray.update(idx, iter.it) + cb.assign(idx, idx + 1) + }) + + val keyType = eltType.selectFields(key) + + val curValsType = PCanonicalArray(eltType) + + val _elementRegion = mb.genFieldThisRef[Region]("szj_region") + + // The algorithm maintains a tournament tree of comparisons between the + // current values of the k streams. The tournament tree is a complete + // binary tree with k leaves. The leaves of the tree are the streams, + // and each internal node represents the "contest" between the "winners" + // of the two subtrees, where the winner is the stream with the smaller + // current key. Each internal node stores the index of the stream which + // *lost* that contest. + // Each time we remove the overall winner, and replace that stream's + // leaf with its next value, we only need to rerun the contests on the + // path from that leaf to the root, comparing the new value with what + // previously lost that contest to the previous overall winner. + + val k = nStreams + // The leaf nodes of the tournament tree, each of which holds a pointer + // to the current value of that stream. + val heads = mb.genFieldThisRef[Array[Long]]("merge_heads") + // The internal nodes of the tournament tree, laid out in breadth-first + // order, each of which holds the index of the stream which lost that + // contest. + val bracket = mb.genFieldThisRef[Array[Int]]("merge_bracket") + // When updating the tournament tree, holds the winner of the subtree + // containing the updated leaf. Otherwise, holds the overall winner, i.e. + // the current least element. + val winner = mb.genFieldThisRef[Int]("merge_winner") + val result = mb.genFieldThisRef[Array[Long]]("merge_result") + val i = mb.genFieldThisRef[Int]("merge_i") + + val curKey = mb.newPField("st_grpby_curkey", keyType.sType) + + val xKey = mb.newEmitField("zipjoin_key", keyType.sType, required = true) + val xElts = mb.newEmitField("zipjoin_elts", curValsType.sType, required = true) + + val joinResult: EmitCode = EmitCode.fromI(mb) { cb => + val newEnv = env.bind((keyRef -> xKey), (valsRef -> xElts)) + emit(joinIR, cb, env = newEnv) + } + + val regionArray: Settable[Array[Region]] = if (streamRequiresMemoryManagement) + mb.genFieldThisRef[Array[Region]]("szj_region_array") + else + null + + val producer = new StreamProducer { + override def method: EmitMethodBuilder[_] = mb + + override val length: Option[EmitCodeBuilder => Code[Int]] = None + + override def initialize(cb: EmitCodeBuilder, outerRegion: Value[Region]): Unit = { + if (streamRequiresMemoryManagement) + cb.assign(regionArray, Code.newArray[Region](nStreams)) + cb.assign(bracket, Code.newArray[Int](k)) + cb.assign(heads, Code.newArray[Long](k)) + cb.forLoop(cb.assign(i, 0), i < k, cb.assign(i, i + 1), { + cb.updateArray(bracket, i, -1) + val eltRegion: Value[Region] = if (streamRequiresMemoryManagement) { + val r = cb.memoize(Region.stagedCreate(Region.REGULAR, outerRegion.getPool())) + cb.updateArray(regionArray, i, r) + r + } else outerRegion + cb += iterArray(i).invoke[Region, Region, Unit]("init", outerRegion, eltRegion) + }) + cb.assign(result, Code._null) + cb.assign(i, 0) + cb.assign(winner, 0) + } + + override val elementRegion: Settable[Region] = _elementRegion + override val requiresMemoryManagementPerElement: Boolean = streamRequiresMemoryManagement + override val LproduceElement: CodeLabel = mb.defineAndImplementLabel { cb => + val LrunMatch = CodeLabel() + val LpullChild = CodeLabel() + val LloopEnd = CodeLabel() + val LaddToResult = CodeLabel() + val LstartNewKey = CodeLabel() + val Lpush = CodeLabel() + + def inSetup: Code[Boolean] = result.isNull + + cb.ifx(inSetup, { + cb.assign(i, 0) + cb.goto(LpullChild) + }, { + cb.ifx(winner.ceq(k), cb.goto(LendOfStream), cb.goto(LstartNewKey)) + }) + + cb.define(Lpush) + cb.assign(xKey, EmitCode.present(cb.emb, curKey)) + cb.assign(xElts, EmitCode.present(cb.emb, curValsType.constructFromElements(cb, elementRegion, k, false) { (cb, i) => + IEmitCode(cb, result(i).ceq(0L), eltType.loadCheapSCode(cb, result(i))) + })) + cb.goto(LproduceElementDone) + + cb.define(LstartNewKey) + cb.forLoop(cb.assign(i, 0), i < k, cb.assign(i, i + 1), { + cb.updateArray(result, i, 0L) + }) + cb.assign(curKey, eltType.loadCheapSCode(cb, heads(winner)).subset(key: _*) + .castTo(cb, elementRegion, curKey.st, true)) + cb.goto(LaddToResult) + + cb.define(LaddToResult) + cb += (result(winner) = heads(winner)) + if (streamRequiresMemoryManagement) { + val r = cb.newLocal[Region]("tzj_winner_region", regionArray(winner)) + cb += elementRegion.trackAndIncrementReferenceCountOf(r) + cb += r.clearRegion() + } + cb.goto(LpullChild) + + val matchIdx = mb.genFieldThisRef[Int]("merge_match_idx") + val challenger = mb.genFieldThisRef[Int]("merge_challenger") + // Compare 'winner' with value in 'matchIdx', loser goes in 'matchIdx', + // winner goes on to next round. A contestant '-1' beats everything + // (negative infinity), a contestant 'k' loses to everything + // (positive infinity), and values in between are indices into 'heads'. + + cb.define(LrunMatch) + cb.assign(challenger, bracket(matchIdx)) + cb.ifx(matchIdx.ceq(0) || challenger.ceq(-1), cb.goto(LloopEnd)) + + val LafterChallenge = CodeLabel() + + cb.ifx(challenger.cne(k), { + val LchallengerWins = CodeLabel() + + cb.ifx(winner.ceq(k), cb.goto(LchallengerWins)) + + val left = eltType.loadCheapSCode(cb, heads(challenger)).subset(key: _*) + val right = eltType.loadCheapSCode(cb, heads(winner)).subset(key: _*) + val ord = StructOrdering.make(left.st, right.st, cb.emb.ecb, missingFieldsEqual = false) + cb.ifx(ord.lteqNonnull(cb, left, right), + cb.goto(LchallengerWins), + cb.goto(LafterChallenge)) + + cb.define(LchallengerWins) + cb.updateArray(bracket, matchIdx, winner) + cb.assign(winner, challenger) + }) + cb.define(LafterChallenge) + cb.assign(matchIdx, matchIdx >>> 1) + cb.goto(LrunMatch) + + cb.define(LloopEnd) + cb.ifx(matchIdx.ceq(0), { + // 'winner' is smallest of all k heads. If 'winner' = k, all heads + // must be k, and all streams are exhausted. + + cb.ifx(inSetup, { + cb.ifx(winner.ceq(k), + cb.goto(LendOfStream), + { + cb.assign(result, Code.newArray[Long](k)) + cb.goto(LstartNewKey) + }) + }, { + cb.ifx(!winner.cne(k), cb.goto(Lpush)) + val left = eltType.loadCheapSCode(cb, heads(winner)).subset(key: _*) + val right = curKey + val ord = StructOrdering.make(left.st, right.st.asInstanceOf[SBaseStruct], + cb.emb.ecb, missingFieldsEqual = false) + cb.ifx(ord.equivNonnull(cb, left, right), cb.goto(LaddToResult), cb.goto(Lpush)) + }) + }, { + // We're still in the setup phase + cb.updateArray(bracket, matchIdx, winner) + cb.assign(i, i + 1) + cb.assign(winner, i) + cb.goto(LpullChild) + }) + + cb.define(LpullChild) + cb.ifx(winner >= nStreams, LendOfStream.goto) // can only happen if k=0 + val winnerIter = cb.memoize(iterArray(winner)) + val winnerNextElt = cb.memoize(winnerIter.invoke[Long]("next")) + cb.ifx(winnerIter.invoke[Boolean]("eos"), { + cb.assign(matchIdx, (winner + k) >>> 1) + cb.assign(winner, k) + }, { + cb.assign(matchIdx, (winner + k) >>> 1) + cb.updateArray(heads, winner, winnerNextElt) + }) + cb.goto(LrunMatch) + } + + override val element: EmitCode = joinResult + + override def close(cb: EmitCodeBuilder): Unit = { + cb.assign(i, 0) + cb.whileLoop(i < nStreams, { + cb += iterArray(i).invoke[Unit]("close") + if (requiresMemoryManagementPerElement) + cb += regionArray(i).invoke[Unit]("invalidate") + cb.assign(i, i + 1) + }) + if (requiresMemoryManagementPerElement) + cb.assign(regionArray, Code._null) + cb.assign(bracket, Code._null) + cb.assign(heads, Code._null) + cb.assign(result, Code._null) + } + } + + SStreamValue(producer) + } + + case x@StreamMultiMerge(as, key) => IEmitCode.multiMapEmitCodes(cb, as.map(a => EmitCode.fromI(mb)(cb => emit(a, cb)))) { children => val producers = children.map(_.asStream.getProducer(mb)) diff --git a/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala b/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala index 0217d38a7e4..e2cc73bf1c0 100644 --- a/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala +++ b/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala @@ -2,26 +2,29 @@ package is.hail.io.vcf import htsjdk.variant.vcf._ import is.hail.annotations._ -import is.hail.asm4s.HailClassLoader +import is.hail.asm4s._ import is.hail.backend.spark.SparkBackend import is.hail.backend.{BroadcastValue, ExecuteContext, HailStateManager} import is.hail.expr.JSONAnnotationImpex import is.hail.expr.ir.lowering.TableStage -import is.hail.expr.ir.{CloseableIterator, GenericLine, GenericLines, GenericTableValue, IR, IRParser, Literal, LowerMatrixIR, MatrixHybridReader, MatrixIR, MatrixLiteral, MatrixReader, TableValue} +import is.hail.expr.ir.streams.StreamProducer +import is.hail.expr.ir.{CloseableIterator, EmitCode, EmitCodeBuilder, EmitMethodBuilder, GenericLine, GenericLines, GenericTableValue, IEmitCode, IR, IRParser, Literal, LowerMatrixIR, MatrixHybridReader, MatrixReader, PartitionReader, TableValue} import is.hail.io.fs.{FS, FileStatus} import is.hail.io.tabix._ -import is.hail.io.vcf.LoadVCF.{getHeaderLines, parseHeader, parseLines} +import is.hail.io.vcf.LoadVCF.{getHeaderLines, parseHeader} import is.hail.io.{VCFAttributes, VCFMetadata} -import is.hail.rvd.{RVD, RVDPartitioner, RVDType} +import is.hail.rvd.{RVDPartitioner, RVDType} import is.hail.sparkextras.ContextRDD import is.hail.types._ import is.hail.types.physical._ +import is.hail.types.physical.stypes.interfaces.{SBaseStructValue, SStreamValue} import is.hail.types.virtual._ import is.hail.utils._ import is.hail.variant._ import org.apache.spark.rdd.RDD import org.apache.spark.sql.Row import org.apache.spark.{Partition, TaskContext} +import org.json4s.JsonAST.{JArray, JObject, JString} import org.json4s.jackson.JsonMethods import org.json4s.{DefaultFormats, Formats, JValue} @@ -42,8 +45,128 @@ class BufferedLineIterator(bit: BufferedIterator[String]) extends htsjdk.tribble } } -case class VCFHeaderInfo(sampleIds: Array[String], infoSignature: PStruct, vaSignature: PStruct, genotypeSignature: PStruct, - filtersAttrs: VCFAttributes, infoAttrs: VCFAttributes, formatAttrs: VCFAttributes, infoFlagFields: Set[String]) +object VCFHeaderInfo { + val headerType: TStruct = TStruct( + "sampleIDs" -> TArray(TString), + "infoFields" -> TArray(TTuple(TString, TString)), + "formatFields" -> TArray(TTuple(TString, TString)), + "filterAttrs" -> TDict(TString, TDict(TString, TString)), + "infoAttrs" -> TDict(TString, TDict(TString, TString)), + "formatAttrs" -> TDict(TString, TDict(TString, TString)), + "infoFlagFields" -> TArray(TString) + ) + + val headerTypePType: PType = PType.canonical(headerType, required = false, innerRequired = true) + + def fromJSON(jv: JValue): VCFHeaderInfo = { + val sampleIDs = (jv \ "sampleIDs").asInstanceOf[JArray].arr.map(_.asInstanceOf[JString].s).toArray + val infoFlagFields = (jv \ "infoFlagFields").asInstanceOf[JArray].arr.map(_.asInstanceOf[JString].s).toSet + + def lookupFields(name: String) = (jv \ name).asInstanceOf[JArray].arr.map { case elt: JArray => + val List(name: JString, typeStr: JString) = elt.arr + name.s -> IRParser.parseType(typeStr.s) + }.toArray + + val infoFields = lookupFields("infoFields") + val formatFields = lookupFields("formatFields") + + def lookupAttrs(name: String) = (jv \ name).asInstanceOf[JObject].obj.toMap + .mapValues { case elt: JObject => + elt.obj.toMap.mapValues(_.asInstanceOf[JString].s) + } + + val filterAttrs = lookupAttrs("filterAttrs") + val infoAttrs = lookupAttrs("infoAttrs") + val formatAttrs = lookupAttrs("formatAttrs") + VCFHeaderInfo(sampleIDs, infoFields, formatFields, filterAttrs, infoAttrs, formatAttrs, infoFlagFields) + } +} + +case class VCFHeaderInfo(sampleIds: Array[String], infoFields: Array[(String, Type)], formatFields: Array[(String, Type)], + filtersAttrs: VCFAttributes, infoAttrs: VCFAttributes, formatAttrs: VCFAttributes, infoFlagFields: Set[String]) { + + def formatCompatible(other: VCFHeaderInfo): Boolean = { + val m = formatFields.toMap + other.formatFields.forall { case (name, t) => m(name) == t} + } + + def infoCompatible(other: VCFHeaderInfo): Boolean = { + val m = infoFields.toMap + other.infoFields.forall { case (name, t) => m.get(name).contains(t) } + } + + def genotypeSignature: TStruct = TStruct(formatFields: _*) + def infoSignature: TStruct = TStruct(infoFields: _*) + + + def getPTypes(arrayElementsRequired: Boolean, entryFloatType: Type, callFields: Set[String]): (PStruct, PStruct, PStruct) = { + + def typeToPType(fdName: String, t: Type, floatType: Type, required: Boolean, isCallField: Boolean): PType = { + t match { + case TString if isCallField => PCanonicalCall(required) + case t if isCallField => + fatal(s"field '$fdName': cannot parse type $t as call field") + case TFloat64 => + PType.canonical(floatType, required) + case TString => + PCanonicalString(required) + case TInt32 => + PInt32(required) + case TBoolean => + PBooleanRequired + case TArray(t2) => + PCanonicalArray(typeToPType(fdName, t2, floatType, arrayElementsRequired, false), required) + } + } + + val infoType = PCanonicalStruct(true, infoFields.map { case (name, t) => + (name, typeToPType(name, t, TFloat64, false, false)) + }: _*) + val formatType = PCanonicalStruct(true, formatFields.map { case (name, t) => + (name, typeToPType(name, t, entryFloatType, false, name == "GT" || callFields.contains(name))) + }: _*) + + val vaSignature = PCanonicalStruct(Array( + PField("rsid", PCanonicalString(), 0), + PField("qual", PFloat64(), 1), + PField("filters", PCanonicalSet(PCanonicalString(true)), 2), + PField("info", infoType, 3)), true) + (infoType, vaSignature, formatType) + } + + def writeToRegion(sm: HailStateManager, r: Region, dropAttrs: Boolean): Long = { + val rvb = new RegionValueBuilder(sm, r) + rvb.start(VCFHeaderInfo.headerTypePType) + rvb.startStruct() + rvb.addAnnotation(rvb.currentType().virtualType, sampleIds.toFastIndexedSeq) + rvb.addAnnotation(rvb.currentType().virtualType, infoFields.map { case (x1, x2) => Row(x1, x2.parsableString()) }.toFastIndexedSeq) + rvb.addAnnotation(rvb.currentType().virtualType, formatFields.map { case (x1, x2) => Row(x1, x2.parsableString()) }.toFastIndexedSeq) + rvb.addAnnotation(rvb.currentType().virtualType, if (dropAttrs) Map.empty else filtersAttrs) + rvb.addAnnotation(rvb.currentType().virtualType, if (dropAttrs) Map.empty else infoAttrs) + rvb.addAnnotation(rvb.currentType().virtualType, if (dropAttrs) Map.empty else formatAttrs) + rvb.addAnnotation(rvb.currentType().virtualType, infoFlagFields.toFastIndexedSeq.sorted) + rvb.result().offset + } + + def toJSON: JValue = { + def fieldsJson(fields: Array[(String, Type)]): JValue = JArray(fields.map { case (name, t) => + JArray(List(JString(name), JString(t.parsableString()))) + }.toList) + + def attrsJson(attrs: Map[String, Map[String, String]]): JValue = JObject(attrs.map { case (name, m) => + (name, JObject(name -> JObject(m.map { case (k, v) => (k, JString(v)) }.toList))) + }.toList) + + JObject( + "sampleIDs" -> JArray(sampleIds.map(JString).toList), + "infoFields" -> fieldsJson(infoFields), + "formatFields" -> fieldsJson(formatFields), + "filtersAttrs" -> attrsJson(filtersAttrs), + "infoAttrs" -> attrsJson(infoAttrs), + "formatAttrs" -> attrsJson(formatAttrs), + "infoFlagFields" -> JArray(infoFlagFields.map(JString).toList)) + } +} class VCFParseError(val msg: String, val pos: Int) extends RuntimeException(msg) @@ -1086,9 +1209,10 @@ class ParseLineContext( val rowType: TStruct, val infoFlagFieldNames: java.util.HashSet[String], val nSamples: Int, - val fileNum: Int + val fileNum: Int, + val entriesName: String ) { - val entryType: TStruct = rowType.fieldOption(LowerMatrixIR.entriesFieldName) match { + val entryType: TStruct = rowType.fieldOption(entriesName) match { case Some(entriesArray) => entriesArray.typ.asInstanceOf[TArray].elementType.asInstanceOf[TStruct] case None => TStruct.empty } @@ -1177,22 +1301,16 @@ object LoadVCF { } def headerField( - line: VCFCompoundHeaderLine, - callFields: Set[String], - floatType: TNumeric, - arrayElementsRequired: Boolean = false - ): ((String, PType), (String, Map[String, String]), Boolean) = { + line: VCFCompoundHeaderLine + ): ((String, Type), (String, Map[String, String]), Boolean) = { val id = line.getID - val isCall = id == "GT" || callFields.contains(id) - val baseType = (line.getType, isCall) match { - case (VCFHeaderLineType.Integer, false) => PInt32() - case (VCFHeaderLineType.Float, false) => PType.canonical(floatType) - case (VCFHeaderLineType.String, true) => PCanonicalCall() - case (VCFHeaderLineType.String, false) => PCanonicalString() - case (VCFHeaderLineType.Character, false) => PCanonicalString() - case (VCFHeaderLineType.Flag, false) => PBoolean(true) - case (_, true) => fatal(s"Can only convert a header line with type 'String' to a call type. Found '${ line.getType }'.") + val baseType = line.getType match { + case VCFHeaderLineType.Integer => TInt32 + case VCFHeaderLineType.Float => TFloat64 + case VCFHeaderLineType.String => TString + case VCFHeaderLineType.Character => TString + case VCFHeaderLineType.Flag => TBoolean } val attrs = Map("Description" -> line.getDescription, @@ -1212,31 +1330,25 @@ object LoadVCF { } else if (baseType.isInstanceOf[PCall]) fatal("fields in 'call_fields' must have 'Number' equal to 1.") else - ((id, PCanonicalArray(baseType.setRequired(arrayElementsRequired))), (id, attrs), isFlag) + ((id, TArray(baseType)), (id, attrs), isFlag) } def headerSignature[T <: VCFCompoundHeaderLine]( lines: java.util.Collection[T], - callFields: Set[String], - floatType: TNumeric, - arrayElementsRequired: Boolean = false - ): (PStruct, VCFAttributes, Set[String]) = { + ): (Array[(String, Type)], VCFAttributes, Set[String]) = { val (fields, attrs, flags) = lines.asScala - .map { line => headerField(line, callFields, floatType, arrayElementsRequired) } + .map { line => headerField(line) } .unzip3 val flagFieldNames = fields.zip(flags) .flatMap { case ((f, _), isFlag) => if (isFlag) Some(f) else None } .toSet - (PCanonicalStruct(true, fields.toArray: _*), attrs.toMap, flagFieldNames) + (fields.toArray, attrs.toMap, flagFieldNames) } def parseHeader( - callFields: Set[String], - floatType: TNumeric, - lines: Array[String], - arrayElementsRequired: Boolean = true + lines: Array[String] ): VCFHeaderInfo = { val codec = new htsjdk.variant.vcf.VCFCodec() // Disable "repairing" of headers by htsjdk according to the VCF standard. @@ -1254,16 +1366,10 @@ object LoadVCF { .toMap val infoHeader = header.getInfoHeaderLines - val (infoSignature, infoAttrs, infoFlagFields) = headerSignature(infoHeader, callFields, TFloat64) + val (infoSignature, infoAttrs, infoFlagFields) = headerSignature(infoHeader) val formatHeader = header.getFormatHeaderLines - val (gSignature, formatAttrs, _) = headerSignature(formatHeader, callFields, floatType, arrayElementsRequired = arrayElementsRequired) - - val vaSignature = PCanonicalStruct(Array( - PField("rsid", PCanonicalString(), 0), - PField("qual", PFloat64(), 1), - PField("filters", PCanonicalSet(PCanonicalString(true)), 2), - PField("info", infoSignature, 3)), true) + val (gSignature, formatAttrs, _) = headerSignature(formatHeader) val headerLine = lines.last if (!(headerLine(0) == '#' && headerLine(1) != '#')) @@ -1276,7 +1382,6 @@ object LoadVCF { VCFHeaderInfo( sampleIds, infoSignature, - vaSignature, gSignature, filterAttrs, infoAttrs, @@ -1294,27 +1399,33 @@ object LoadVCF { .toArray } + def getVCFHeaderInfo(fs: FS, file: String, filter: String, find: String, replace: String): VCFHeaderInfo = { + parseHeader(getHeaderLines(fs, file, TextInputFilterAndReplace(Option(filter), Option(find), Option(replace)))) + } + def parseLine( - rgBc: Option[BroadcastValue[ReferenceGenome]], + rg: Option[ReferenceGenome], contigRecoding: Map[String, String], skipInvalidLoci: Boolean, rowPType: PStruct, rvb: RegionValueBuilder, parseLineContext: ParseLineContext, - vcfLine: VCFLine): Boolean = { + vcfLine: VCFLine, + entriesFieldName: String = LowerMatrixIR.entriesFieldName, + uidFieldName: String = MatrixReader.rowUIDFieldName): Boolean = { val hasLocus = rowPType.hasField("locus") val hasAlleles = rowPType.hasField("alleles") val hasRSID = rowPType.hasField("rsid") - val hasEntries = rowPType.hasField(LowerMatrixIR.entriesFieldName) - val hasRowUID = rowPType.hasField(MatrixReader.rowUIDFieldName) + val hasEntries = rowPType.hasField(entriesFieldName) + val hasRowUID = rowPType.hasField(uidFieldName) rvb.start(rowPType) rvb.startStruct() - val present = vcfLine.parseAddVariant(rvb, rgBc.map(_.value), contigRecoding, hasLocus, hasAlleles, hasRSID, skipInvalidLoci) + val present = vcfLine.parseAddVariant(rvb, rg, contigRecoding, hasLocus, hasAlleles, hasRSID, skipInvalidLoci) if (!present) return present - parseLine(parseLineContext, vcfLine, rvb, !hasEntries) + parseLineInner(parseLineContext, vcfLine, rvb, !hasEntries) if (hasRowUID) { rvb.startTuple() @@ -1405,12 +1516,12 @@ object LoadVCF { def parseHeaderMetadata(fs: FS, callFields: Set[String], entryFloatType: TNumeric, headerFile: String): VCFMetadata = { val headerLines = getHeaderLines(fs, headerFile, TextInputFilterAndReplace()) - val VCFHeaderInfo(_, _, _, _, filterAttrs, infoAttrs, formatAttrs, _) = parseHeader(callFields, entryFloatType, headerLines) + val header = parseHeader(headerLines) - Map("filter" -> filterAttrs, "info" -> infoAttrs, "format" -> formatAttrs) + Map("filter" -> header.filtersAttrs, "info" -> header.infoAttrs, "format" -> header.formatAttrs) } - def parseLine( + def parseLineInner( c: ParseLineContext, l: VCFLine, rvb: RegionValueBuilder, @@ -1583,7 +1694,7 @@ object MatrixVCFReader { val entryFloatType = LoadVCF.getEntryFloatType(params.entryFloatTypeName) val headerLines1 = getHeaderLines(fs, params.headerFile.getOrElse(fileStatuses.head.getPath), params.filterAndReplace) - val header1 = parseHeader(params.callFields, entryFloatType, headerLines1, arrayElementsRequired = params.arrayElementsRequired) + val header1 = parseHeader(headerLines1) if (fileStatuses.length > 1) { if (params.headerFile.isEmpty) { @@ -1601,9 +1712,7 @@ object MatrixVCFReader { fs.setConfiguration(fsConfig) val file = new String(bytes) - val hd = parseHeader( - localCallFields, localFloatType, getHeaderLines(fs, file, localFilterAndReplace), - arrayElementsRequired = localArrayElementsRequired) + val hd = parseHeader(getHeaderLines(fs, file, localFilterAndReplace)) val hd1 = header1Bc.value if (params.sampleIDs.isEmpty && hd1.sampleIds.length != hd.sampleIds.length) { @@ -1626,17 +1735,17 @@ object MatrixVCFReader { } } - if (hd1.genotypeSignature != hd.genotypeSignature) + if (!hd.formatCompatible(hd1)) fatal( s"""invalid genotype signature: expected signatures to be identical for all inputs. - | ${ files(0) }: ${ hd1.genotypeSignature.virtualType.toString } - | $file: ${ hd.genotypeSignature.virtualType.toString }""".stripMargin) + | ${ files(0) }: ${ hd1.genotypeSignature.toString } + | $file: ${ hd.genotypeSignature.toString }""".stripMargin) - if (hd1.vaSignature != hd.vaSignature) + if (!hd.infoCompatible(hd1)) fatal( s"""invalid variant annotation signature: expected signatures to be identical for all inputs. Check that all files have same INFO fields. - | ${ files(0) }: ${ hd1.vaSignature.virtualType.toString } - | $file: ${ hd.vaSignature.virtualType.toString }""".stripMargin) + | ${ files(0) }: ${ hd1.infoSignature.toString } + | $file: ${ hd.infoSignature.toString }""".stripMargin) bytes } @@ -1644,12 +1753,11 @@ object MatrixVCFReader { } } - val VCFHeaderInfo(hdrSampleIDs, _, vaSignature, genotypeSignature, _, _, _, infoFlagFieldNames) = header1 - val sampleIDs = params.sampleIDs.map(_.toArray).getOrElse(hdrSampleIDs) + val sampleIDs = params.sampleIDs.map(_.toArray).getOrElse(header1.sampleIds) LoadVCF.warnDuplicates(sampleIDs) - new MatrixVCFReader(params, fileStatuses, infoFlagFieldNames, referenceGenome, vaSignature, genotypeSignature, sampleIDs) + new MatrixVCFReader(params, fileStatuses, referenceGenome, header1) } def fromJValue(ctx: ExecuteContext, jv: JValue): MatrixVCFReader = { @@ -1684,17 +1792,23 @@ case class MatrixVCFReaderParameters( class MatrixVCFReader( val params: MatrixVCFReaderParameters, fileStatuses: IndexedSeq[FileStatus], - infoFlagFieldNames: Set[String], referenceGenome: Option[ReferenceGenome], - vaSignature: PStruct, - genotypeSignature: PStruct, - sampleIDs: Array[String] + header: VCFHeaderInfo ) extends MatrixHybridReader { require(params.partitionsJSON.isEmpty || fileStatuses.length == 1, "reading with partitions can currently only read a single path") + val sampleIDs = params.sampleIDs.map(_.toArray).getOrElse(header.sampleIds) + + LoadVCF.warnDuplicates(sampleIDs) + def rowUIDType = TTuple(TInt64, TInt64) def colUIDType = TInt64 + val (infoPType, rowValuePType, formatPType) = header.getPTypes( + params.arrayElementsRequired, + IRParser.parseType(params.entryFloatTypeName), + params.callFields) + def fullMatrixTypeWithoutUIDs: MatrixType = MatrixType( globalType = TStruct.empty, colType = TStruct("s" -> TString), @@ -1703,19 +1817,19 @@ class MatrixVCFReader( Array( "locus" -> TLocus.schemaFromRG(referenceGenome.map(_.name)), "alleles" -> TArray(TString)) - ++ vaSignature.fields.map(f => f.name -> f.typ.virtualType): _*), + ++ rowValuePType.fields.map(f => f.name -> f.typ.virtualType): _*), rowKey = Array("locus", "alleles"), // rowKey = Array.empty[String], - entryType = genotypeSignature.virtualType) + entryType = formatPType.virtualType) val fullRVDType = RVDType( PCanonicalStruct(true, FastIndexedSeq( "locus" -> PCanonicalLocus.schemaFromRG(referenceGenome.map(_.name), true), "alleles" -> PCanonicalArray(PCanonicalString(true), true)) - ++ vaSignature.fields.map { f => f.name -> f.typ } + ++ rowValuePType.fields.map { f => f.name -> f.typ } ++ FastIndexedSeq( - LowerMatrixIR.entriesFieldName -> PCanonicalArray(genotypeSignature, true), + LowerMatrixIR.entriesFieldName -> PCanonicalArray(formatPType, true), rowUIDFieldName -> PCanonicalTuple(true, PInt64Required, PInt64Required)): _*), fullType.key) @@ -1766,14 +1880,14 @@ class MatrixVCFReader( val localArrayElementsRequired = params.arrayElementsRequired val localContigRecoding = params.contigRecoding val localSkipInvalidLoci = params.skipInvalidLoci - val localInfoFlagFieldNames = infoFlagFieldNames + val localInfoFlagFieldNames = header.infoFlagFields val localNSamples = nCols val localFilterAndReplace = params.filterAndReplace val part = partitioner(ctx.stateManager) val lines = part match { case Some(partitioner) => - GenericLines.readTabix(fs, fileStatuses(0), localContigRecoding, partitioner.rangeBounds) + GenericLines.readTabix(fs, fileStatuses(0).getPath, localContigRecoding, partitioner.rangeBounds) case None => GenericLines.read(fs, fileStatuses, params.nPartitions, params.blockSizeInMB, params.minPartitions, params.gzAsBGZ, params.forceGZ) } @@ -1793,7 +1907,7 @@ class MatrixVCFReader( { (region: Region, theHailClassLoader: HailClassLoader, fs: FS, context: Any) => val fileNum = context.asInstanceOf[Row].getInt(1) - val parseLineContext = new ParseLineContext(requestedType, makeJavaSet(localInfoFlagFieldNames), localNSamples, fileNum) + val parseLineContext = new ParseLineContext(requestedType, makeJavaSet(localInfoFlagFieldNames), localNSamples, fileNum, LowerMatrixIR.entriesFieldName) val rvb = new RegionValueBuilder(sm, region) @@ -1812,7 +1926,7 @@ class MatrixVCFReader( rvb.clear() try { val vcfLine = new VCFLine(newText, line.fileNum, line.offset, localArrayElementsRequired, abs, abi, abf, abd) - LoadVCF.parseLine(rgBc, localContigRecoding, localSkipInvalidLoci, + LoadVCF.parseLine(rgBc.map(_.value), localContigRecoding, localSkipInvalidLoci, requestedPType, rvb, parseLineContext, vcfLine) } catch { case e: Exception => @@ -1869,156 +1983,92 @@ class MatrixVCFReader( } } -class VCFsReader( - ctx: ExecuteContext, - files: Array[String], +case class GVCFPartitionReader(header: VCFHeaderInfo, callFields: Set[String], - entryFloatTypeName: String, + entryFloatType: Type, + arrayElementsRequired: Boolean, rg: Option[String], contigRecoding: Map[String, String], - arrayElementsRequired: Boolean, skipInvalidLoci: Boolean, filterAndReplace: TextInputFilterAndReplace, - partitionsJSON: String, partitionsTypeStr: String, - externalSampleIds: Option[Array[Array[String]]], - externalHeader: Option[String]) { - - require(!(externalSampleIds.isEmpty ^ externalHeader.isEmpty)) - - private val fs = ctx.fs - private val fsBc = fs.broadcast - - private val referenceGenome = rg.map(ctx.getReference) + entriesFieldName: String, + uidFieldName: String) extends PartitionReader { - referenceGenome.foreach(_.validateContigRemap(contigRecoding)) + lazy val contextType: TStruct = TStruct( + "fileNum" -> TInt32, + "path" -> TString, + "contig" -> TString, + "start" -> TInt32, + "end" -> TInt32) - val reverseContigMapping: Map[String, String] = - contigRecoding.toArray - .groupBy(_._2) - .map { case (target, mappings) => - if (mappings.length > 1) - fatal(s"contig_recoding may not map multiple contigs to the same target contig, " + - s"due to ambiguity when querying the tabix index." + - s"\n Duplicate mappings: ${ mappings.map(_._1).mkString(",") } all map to ${ target }") - (target, mappings.head._1) - }.toMap + lazy val (infoType, rowValueType, entryType) = header.getPTypes(arrayElementsRequired, entryFloatType, callFields) - private val locusType = TLocus.schemaFromRG(rg) - private val rowKeyType = TStruct("locus" -> locusType) + lazy val fullRowPType: PCanonicalStruct = PCanonicalStruct(true, + FastIndexedSeq(("locus", PCanonicalLocus.schemaFromRG(rg, true)), ("alleles", PCanonicalArray(PCanonicalString(true), true))) + ++ rowValueType.fields.map { f => (f.name, f.typ) } + ++ Array(entriesFieldName -> PCanonicalArray(entryType, true), + uidFieldName -> PCanonicalTuple(true, PInt64Required, PInt64Required)): _*) - private val file1 = files.head - private val headerLines1 = getHeaderLines(fs, externalHeader.getOrElse(file1), filterAndReplace) - private val entryFloatType = LoadVCF.getEntryFloatType(entryFloatTypeName) - private val header1 = parseHeader(callFields, entryFloatType, headerLines1, arrayElementsRequired = arrayElementsRequired) + lazy val fullRowType: TStruct = fullRowPType.virtualType - private val kType = TStruct("locus" -> locusType, "alleles" -> TArray(TString)) - - val typ = MatrixType( - TStruct.empty, - colType = TStruct("s" -> TString), - colKey = Array("s"), - rowType = kType ++ header1.vaSignature.virtualType, - rowKey = Array("locus"), - entryType = header1.genotypeSignature.virtualType) - - val fullRVDType = RVDType(PCanonicalStruct(true, - FastIndexedSeq(("locus", PCanonicalLocus.schemaFromRG(rg, true)), ("alleles", PCanonicalArray(PCanonicalString(true), true))) - ++ header1.vaSignature.fields.map { f => (f.name, f.typ) } - ++ Array(LowerMatrixIR.entriesFieldName -> PCanonicalArray(header1.genotypeSignature, true)): _*), - typ.rowKey) - - val partitioner: RVDPartitioner = { - val partitionsType = IRParser.parseType(partitionsTypeStr) - val jv = JsonMethods.parse(partitionsJSON) - val rangeBounds = JSONAnnotationImpex.importAnnotation(jv, partitionsType) - .asInstanceOf[IndexedSeq[Interval]] - - rangeBounds.foreach { bound => - if (!(bound.includesStart && bound.includesEnd)) - fatal("range bounds must be inclusive") - - val start = bound.start.asInstanceOf[Row].getAs[Locus](0) - val end = bound.end.asInstanceOf[Row].getAs[Locus](0) - if (start.contig != end.contig) - fatal(s"partition spec must not cross contig boundaries, start: ${start.contig} | end: ${end.contig}") - } - - new RVDPartitioner( - ctx.stateManager, - Array("locus"), - rowKeyType, - rangeBounds) - } - - val partitions: Array[Partition] = partitioner.rangeBounds.zipWithIndex.map { case (b, i) => - val start = b.start.asInstanceOf[Row].getAs[Locus](0) - val end = b.end.asInstanceOf[Row].getAs[Locus](0) - PartitionedVCFPartition(i, start.contig, start.position, end.position) - } - - private val fileInfo: Array[Array[String]] = externalSampleIds.getOrElse { - val localBcFS = fsBc - val localFile1 = file1 - val localEntryFloatType = entryFloatType - val localCallFields = callFields - val localArrayElementsRequired = arrayElementsRequired - val localFilterAndReplace = filterAndReplace - val localGenotypeSignature = header1.genotypeSignature - val localVASignature = header1.vaSignature - - SparkBackend.sparkContext("VCFsReader.fileInfo").parallelize(files, files.length).map { file => - val fs = localBcFS.value - val headerLines = getHeaderLines(fs, file, localFilterAndReplace) - val header = parseHeader( - localCallFields, localEntryFloatType, headerLines, arrayElementsRequired = localArrayElementsRequired) - - if (header.genotypeSignature != localGenotypeSignature) - fatal( - s"""invalid genotype signature: expected signatures to be identical for all inputs. - | $localFile1: $localGenotypeSignature - | $file: ${header.genotypeSignature}""".stripMargin) - - if (header.vaSignature != localVASignature) - fatal( - s"""invalid variant annotation signature: expected signatures to be identical for all inputs. - | $localFile1: $localVASignature - | $file: ${header.vaSignature}""".stripMargin) + def rowRequiredness(requestedType: TStruct): RStruct = + VirtualTypeWithReq(tcoerce[PStruct](fullRowPType.subsetTo(requestedType))).r.asInstanceOf[RStruct] + override def toJValue: JValue = { + implicit val formats: Formats = DefaultFormats + decomposeWithName(this, "MatrixVCFReader") + } + def emitStream( + ctx: ExecuteContext, + cb: EmitCodeBuilder, + mb: EmitMethodBuilder[_], + context: EmitCode, + requestedType: TStruct + ): IEmitCode = { + context.toI(cb).map(cb) { case ctxValue: SBaseStructValue => + val fileNum = cb.memoizeField(ctxValue.loadField(cb, "fileNum").get(cb).asInt32.value) + val filePath = cb.memoizeField(ctxValue.loadField(cb, "path").get(cb).asString.loadString(cb)) + val contig = cb.memoizeField(ctxValue.loadField(cb, "contig").get(cb).asString.loadString(cb)) + val start = cb.memoizeField(ctxValue.loadField(cb, "start").get(cb).asInt32.value) + val end = cb.memoizeField(ctxValue.loadField(cb, "end").get(cb).asInt32.value) + + val requestedPType = fullRowPType.subsetTo(requestedType).asInstanceOf[PStruct] + val eltRegion = mb.genFieldThisRef[Region]("gvcf_elt_region") + val iter = mb.genFieldThisRef[TabixReadVCFIterator]("gvcf_iter") + val currentElt = mb.genFieldThisRef[Long]("curr_elt") + + SStreamValue(new StreamProducer { + override def method: EmitMethodBuilder[_] = mb + override val length: Option[EmitCodeBuilder => Code[Int]] = None + + override def initialize(cb: EmitCodeBuilder, outerRegion: Value[Region]): Unit = { + cb.assign(iter, Code.newInstance[TabixReadVCFIterator]( + Array[Class[_]](classOf[FS], classOf[String], classOf[Map[String, String]], + classOf[Int], classOf[String], classOf[Int], classOf[Int], + classOf[HailStateManager], classOf[Region], classOf[Region], + classOf[PStruct], classOf[TextInputFilterAndReplace], classOf[Set[String]], + classOf[Int], classOf[ReferenceGenome], classOf[Boolean], classOf[Boolean], + classOf[String], classOf[String]), + Array[Code[_]](mb.getFS, filePath, mb.getObject(contigRecoding), fileNum, contig, start, end, + cb.emb.getObject(cb.emb.ecb.ctx.stateManager), outerRegion, eltRegion, mb.getPType(requestedPType), mb.getObject(filterAndReplace), + mb.getObject(header.infoFlagFields), const(header.sampleIds.length), rg.map(mb.getReferenceGenome).getOrElse(Code._null[ReferenceGenome]), + const(arrayElementsRequired), const(skipInvalidLoci), const(entriesFieldName), const(uidFieldName)) + )) + } - header.sampleIds + override val elementRegion: Settable[Region] = eltRegion + override val requiresMemoryManagementPerElement: Boolean = true + override val LproduceElement: CodeLabel = mb.defineAndImplementLabel { cb => + cb.assign(currentElt, iter.invoke[Region, Long]("next", eltRegion)) + cb.ifx(currentElt ceq 0L, cb.goto(LendOfStream), cb.goto(LproduceElementDone)) + } + override val element: EmitCode = EmitCode.fromI(mb)(cb => IEmitCode.present(cb, requestedPType.loadCheapSCode(cb, currentElt))) + override def close(cb: EmitCodeBuilder): Unit = { + cb += iter.invoke[Unit]("close") + cb.assign(iter, Code._null) + } + }) } - .collect() - } - - def readFile(ctx: ExecuteContext, file: String, i: Int): MatrixIR = { - val sampleIDs = fileInfo(i) - val localInfoFlagFieldNames = header1.infoFlagFields - val localTyp = typ - val tt = localTyp.canonicalTableType - val rvdType = fullRVDType - - val lines = ContextRDD.weaken( - new PartitionedVCFRDD(ctx.fsBc, file, reverseContigMapping, partitions)) - val parsedLines = parseLines { () => - new ParseLineContext(tt.rowType, - makeJavaSet(localInfoFlagFieldNames), - sampleIDs.length, - i) - } { (c, l, rvb) => - LoadVCF.parseLine(c, l, rvb) - }(lines, rvdType.rowType, referenceGenome.map(_.broadcast), contigRecoding, arrayElementsRequired, skipInvalidLoci) - - val rvd = RVD(rvdType, - partitioner, - parsedLines) - - MatrixLiteral(ctx, typ, rvd, Row.empty, sampleIDs.map(Row(_))) - } - - def read(ctx: ExecuteContext): Array[MatrixIR] = { - files.zipWithIndex.map { case (file, i) => - readFile(ctx, file, i) - } } } diff --git a/hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala b/hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala new file mode 100644 index 00000000000..fe260729212 --- /dev/null +++ b/hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala @@ -0,0 +1,115 @@ +package is.hail.io.vcf + +import is.hail.annotations.{Region, RegionValueBuilder, SafeRow} +import is.hail.backend.HailStateManager +import is.hail.expr.ir.{CloseableIterator, GenericLine} +import is.hail.io.fs.{FS, Positioned} +import is.hail.io.tabix.{TabixLineIterator, TabixReader} +import is.hail.types.physical.PStruct +import is.hail.utils.{MissingArrayBuilder, TextInputFilterAndReplace, fatal, makeJavaSet} +import is.hail.variant.ReferenceGenome + +class TabixReadVCFIterator(fs: FS, file: String, contigMapping: Map[String, String], + fileNum: Int, chrom: String, start: Int, end: Int, + sm: HailStateManager, partitionRegion: Region, elementRegion: Region, requestedPType: PStruct, + filterAndReplace: TextInputFilterAndReplace, infoFlagFieldNames: Set[String], nSamples: Int, _rg: ReferenceGenome, + arrayElementsRequired: Boolean, skipInvalidLoci: Boolean, entriesFieldName: String, uidFieldName: String) { + val chromToQuery = contigMapping.iterator.find(_._2 == chrom).map(_._1).getOrElse(chrom) + + val rg = Option(_rg) + + val reg = { + val r = new TabixReader(file, fs) + val tid = r.chr2tid(chromToQuery) + r.queryPairs(tid, start - 1, end) + } + + val linesIter = if (reg.isEmpty) { + CloseableIterator.empty + } else { + new CloseableIterator[GenericLine] { + private[this] val lines = new TabixLineIterator(fs, file, reg) + private[this] var l = lines.next() + private[this] var curIdx: Long = lines.getCurIdx() + private[this] val inner = new Iterator[GenericLine] { + def hasNext: Boolean = l != null + + def next(): GenericLine = { + assert(l != null) + val n = l + val idx = curIdx + l = lines.next() + curIdx = lines.getCurIdx() + if (l == null) + lines.close() + val bytes = n.getBytes + new GenericLine(file, 0, idx, bytes, bytes.length) + } + }.filter { gl => + val s = gl.toString + val t1 = s.indexOf('\t') + val t2 = s.indexOf('\t', t1 + 1) + + val chr = s.substring(0, t1) + val pos = s.substring(t1 + 1, t2).toInt + + if (chr != chrom) { + throw new RuntimeException(s"bad chromosome! ${ chrom }, $s") + } + start <= pos && pos <= end + } + + def hasNext: Boolean = inner.hasNext + + def next(): GenericLine = inner.next() + + def close(): Unit = lines.close() + } + } + + + val transformer = filterAndReplace.transformer() + val parseLineContext = new ParseLineContext(requestedPType.virtualType, makeJavaSet(infoFlagFieldNames), nSamples, fileNum, entriesFieldName) + + val rvb = new RegionValueBuilder(sm) + + val abs = new MissingArrayBuilder[String] + val abi = new MissingArrayBuilder[Int] + val abf = new MissingArrayBuilder[Float] + val abd = new MissingArrayBuilder[Double] + + // 0 if EOS + def next(elementRegion: Region): Long = { + + var done = false + while (!done && linesIter.hasNext) { + val line = linesIter.next() + val text = line.toString + val newText = transformer(text) + done = (newText != null) && { + rvb.clear() + rvb.set(elementRegion) + try { + val vcfLine = new VCFLine(newText, line.fileNum, line.offset, arrayElementsRequired, abs, abi, abf, abd) + val pl = LoadVCF.parseLine(rg, contigMapping, skipInvalidLoci, + requestedPType, rvb, parseLineContext, vcfLine, entriesFieldName, uidFieldName) + pl + } catch { + case e: Exception => + fatal(s"${ line.file }:offset ${ line.offset }: error while parsing line\n" + + s"$newText\n", e) + } + } + } + + if (done) { + rvb.result().offset + } else + 0L + } + + def close(): Unit = { + linesIter.close() + } +} + diff --git a/hail/src/test/scala/is/hail/expr/ir/IRSuite.scala b/hail/src/test/scala/is/hail/expr/ir/IRSuite.scala index b5b2de2250b..c244c624b10 100644 --- a/hail/src/test/scala/is/hail/expr/ir/IRSuite.scala +++ b/hail/src/test/scala/is/hail/expr/ir/IRSuite.scala @@ -3124,19 +3124,6 @@ class IRSuite extends HailSuite { assert(x2 eq cached) } - @Test def testContextSavedMatrixIR() { - val cached = MatrixIR.range(3, 8, None) - val id = hc.addIrVector(Array(cached)) - val s = s"(JavaMatrixVectorRef $id 0)" - val x2 = ExecuteContext.scoped() { ctx => - IRParser.parse_matrix_ir(s, IRParserEnvironment(ctx, irMap = Map.empty)) - } - assert(cached eq x2) - - is.hail.HailContext.pyRemoveIrVector(id) - assert(hc.irVectors.get(id) eq None) - } - @Test def testArrayContinuationDealsWithIfCorrectly() { val ir = ToArray(StreamMap( If(IsNA(In(0, TBoolean)), From 3e0bb6f6ae67269500903c9a8b83098cbba40007 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 5 Jul 2023 19:41:14 -0400 Subject: [PATCH 007/180] [hailctl] Restore pkgs alias for dataproc start packages option (#13220) This got dropped in the move to typer. --- hail/python/hailtop/hailctl/dataproc/cli.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hail/python/hailtop/hailctl/dataproc/cli.py b/hail/python/hailtop/hailctl/dataproc/cli.py index a836b544bdd..1347617a5f3 100644 --- a/hail/python/hailtop/hailctl/dataproc/cli.py +++ b/hail/python/hailtop/hailctl/dataproc/cli.py @@ -113,7 +113,12 @@ def start( properties: Ann[Optional[str], Opt(help='Additional configuration properties for the cluster.')] = None, metadata: Ann[Optional[str], Opt(help='Comma-separated list of metadata to add: KEY1=VALUE1,KEY2=VALUE2')] = None, packages: Ann[ - Optional[str], Opt(help='Comma-separated list of Python packages to be installed on the master node.') + Optional[str], + Opt( + '--packages', + '--pkgs', + help='Comma-separated list of Python packages to be installed on the master node.', + ), ] = None, project: Ann[Optional[str], Opt(help='GCP project to start cluster (defaults to currently set project).')] = None, configuration: Ann[ From b7cc5f37686c61b1a78bab49a6fbe3f740c6884e Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 6 Jul 2023 15:02:38 -0400 Subject: [PATCH 008/180] [batch] Reuse AzureCredentials on the worker (#13225) Azure default credentials will use the metadata server when available so we can just use those instead of manually reaching out to the metadata server. --- batch/batch/cloud/azure/worker/worker_api.py | 24 ++++--------------- .../hailtop/aiocloud/aioazure/credentials.py | 6 ++++- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/batch/batch/cloud/azure/worker/worker_api.py b/batch/batch/cloud/azure/worker/worker_api.py index 06c2d649f20..0f035fe888a 100644 --- a/batch/batch/cloud/azure/worker/worker_api.py +++ b/batch/batch/cloud/azure/worker/worker_api.py @@ -29,8 +29,8 @@ def from_env(): def __init__(self, subscription_id: str, resource_group: str, acr_url: str): self.subscription_id = subscription_id self.resource_group = resource_group - self.acr_refresh_token = AcrRefreshToken(acr_url, AadAccessToken()) self.azure_credentials = aioazure.AzureCredentials.default_credentials() + self.acr_refresh_token = AcrRefreshToken(acr_url, self.azure_credentials) self._blobfuse_credential_files: Dict[str, str] = {} def create_disk(self, instance_name: str, disk_name: str, size_in_gb: int, mount_path: str) -> AzureDisk: @@ -139,34 +139,18 @@ async def _fetch(self, session: httpx.ClientSession) -> Tuple[str, int]: raise NotImplementedError() -class AadAccessToken(LazyShortLivedToken): - async def _fetch(self, session: httpx.ClientSession) -> Tuple[str, int]: - # https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http - params = {'api-version': '2018-02-01', 'resource': 'https://management.azure.com/'} - resp_json = await retry_transient_errors( - session.get_read_json, - 'http://169.254.169.254/metadata/identity/oauth2/token', - headers={'Metadata': 'true'}, - params=params, - timeout=aiohttp.ClientTimeout(total=60), # type: ignore - ) - access_token: str = resp_json['access_token'] - expiration_time_ms = int(resp_json['expires_on']) * 1000 - return access_token, expiration_time_ms - - class AcrRefreshToken(LazyShortLivedToken): - def __init__(self, acr_url: str, aad_access_token: AadAccessToken): + def __init__(self, acr_url: str, credentials: aioazure.AzureCredentials): super().__init__() self.acr_url: str = acr_url - self.aad_access_token: AadAccessToken = aad_access_token + self.credentials = credentials async def _fetch(self, session: httpx.ClientSession) -> Tuple[str, int]: # https://github.com/Azure/acr/blob/main/docs/AAD-OAuth.md#calling-post-oauth2exchange-to-get-an-acr-refresh-token data = { 'grant_type': 'access_token', 'service': self.acr_url, - 'access_token': await self.aad_access_token.token(session), + 'access_token': (await self.credentials.access_token()).token, } resp_json = await retry_transient_errors( session.post_read_json, diff --git a/hail/python/hailtop/aiocloud/aioazure/credentials.py b/hail/python/hailtop/aiocloud/aioazure/credentials.py index de4402ee292..25abbeafb66 100644 --- a/hail/python/hailtop/aiocloud/aioazure/credentials.py +++ b/hail/python/hailtop/aiocloud/aioazure/credentials.py @@ -50,11 +50,15 @@ def __init__(self, credential, scopes: Optional[List[str]] = None): self.scopes = scopes async def auth_headers(self): + access_token = await self.access_token() + return {'Authorization': f'Bearer {access_token.token}'} # type: ignore + + async def access_token(self): now = time.time() if self._access_token is None or (self._expires_at is not None and now > self._expires_at): self._access_token = await self.get_access_token() self._expires_at = now + (self._access_token.expires_on - now) // 2 # type: ignore - return {'Authorization': f'Bearer {self._access_token.token}'} # type: ignore + return self._access_token async def get_access_token(self): return await self.credential.get_token(*self.scopes) From 07c49306a96c5fe6620f16307ba70dd2d08f628c Mon Sep 17 00:00:00 2001 From: Edmund Higham Date: Fri, 7 Jul 2023 17:07:00 -0400 Subject: [PATCH 009/180] Fix #13045 - Comparison of Structs and Struct Exprs (#13226) RR: https://github.com/hail-is/hail/issues/13045 RR: https://github.com/hail-is/hail/issues/13046 Support symmetric comparison of structs and struct expressions. Provide better error messages when attempting to construct literals from expressions with free variables. --- hail/python/hail/expr/functions.py | 15 ++++++++++++- hail/python/hail/genetics/call.py | 6 ++--- hail/python/hail/genetics/locus.py | 8 +++---- hail/python/hail/utils/interval.py | 11 +++++----- hail/python/hail/utils/linkedlist.py | 8 ++++--- hail/python/hail/utils/struct.py | 4 +++- hail/python/test/hail/expr/test_functions.py | 7 ++++++ hail/python/test/hail/genetics/test_call.py | 7 ++++++ hail/python/test/hail/genetics/test_locus.py | 23 +++++++++++--------- hail/python/test/hail/utils/test_utils.py | 19 ++++++++++++++++ 10 files changed, 81 insertions(+), 27 deletions(-) diff --git a/hail/python/hail/expr/functions.py b/hail/python/hail/expr/functions.py index ffa37438f70..938a4a6ec6c 100644 --- a/hail/python/hail/expr/functions.py +++ b/hail/python/hail/expr/functions.py @@ -233,11 +233,17 @@ def literal(x: Any, dtype: Optional[Union[HailType, str]] = None): ------- :class:`.Expression` """ - wrapper = {'has_expr': False} + wrapper = {'has_expr': False, 'has_free_vars': False} def typecheck_expr(t, x): if isinstance(x, Expression): wrapper['has_expr'] = True + wrapper['has_free_vars'] |= ( + builtins.len(x._ir.free_vars) > 0 or + builtins.len(x._ir.free_agg_vars) > 0 or + builtins.len(x._ir.free_scan_vars) > 0 + ) + if x.dtype != t: raise TypeError(f"'literal': type mismatch: expected '{t}', found '{x.dtype}'") elif x._indices.source is not None: @@ -265,6 +271,13 @@ def typecheck_expr(t, x): raise TypeError("'literal': object did not match the passed type '{}'" .format(dtype)) from e + if wrapper['has_free_vars']: + raise ValueError( + "'literal' cannot be used with hail expressions that depend " + "on other expressions. Use expression 'x' directly " + "instead of passing it to 'literal'." + ) + if wrapper['has_expr']: return literal(hl.eval(to_expr(x, dtype)), dtype) diff --git a/hail/python/hail/genetics/call.py b/hail/python/hail/genetics/call.py index 36c9efd4742..e31d67263e9 100644 --- a/hail/python/hail/genetics/call.py +++ b/hail/python/hail/genetics/call.py @@ -70,9 +70,9 @@ def __repr__(self): return 'Call(alleles=%s, phased=%s)' % (self._alleles, self._phased) def __eq__(self, other): - return (isinstance(other, Call) - and self._phased == other._phased - and self._alleles == other._alleles) + return ( self._phased == other._phased and + self._alleles == other._alleles + ) if isinstance(other, Call) else NotImplemented def __hash__(self): return hash(self._phased) ^ hash(tuple(self._alleles)) diff --git a/hail/python/hail/genetics/locus.py b/hail/python/hail/genetics/locus.py index 68145dc8ccf..97029f60a6a 100644 --- a/hail/python/hail/genetics/locus.py +++ b/hail/python/hail/genetics/locus.py @@ -51,10 +51,10 @@ def __repr__(self): return 'Locus(contig=%s, position=%s, reference_genome=%s)' % (self.contig, self.position, self._rg) def __eq__(self, other): - return (isinstance(other, Locus) - and self._contig == other._contig - and self._position == other._position - and self._rg == other._rg) + return ( self._contig == other._contig and + self._position == other._position and + self._rg == other._rg + ) if isinstance(other, Locus) else NotImplemented def __hash__(self): return hash(self._contig) ^ hash(self._position) ^ hash(self._rg) diff --git a/hail/python/hail/utils/interval.py b/hail/python/hail/utils/interval.py index 0f1733805b3..0e08041e5c8 100644 --- a/hail/python/hail/utils/interval.py +++ b/hail/python/hail/utils/interval.py @@ -67,11 +67,12 @@ def __repr__(self): .format(repr(self.start), repr(self.end), repr(self.includes_start), repr(self._includes_end)) def __eq__(self, other): - return (isinstance(other, Interval) - and self._start == other._start - and self._end == other._end - and self._includes_start == other._includes_start - and self._includes_end == other._includes_end) + return ( self._start == other._start and + self._end == other._end and + self._includes_start == other._includes_start and + self._includes_end == other._includes_end + ) if isinstance(other, Interval) else NotImplemented + def __hash__(self): return hash(self._start) ^ hash(self._end) ^ hash(self._includes_start) ^ hash(self._includes_end) diff --git a/hail/python/hail/utils/linkedlist.py b/hail/python/hail/utils/linkedlist.py index 508278dc130..d1a30ab4aab 100644 --- a/hail/python/hail/utils/linkedlist.py +++ b/hail/python/hail/utils/linkedlist.py @@ -42,13 +42,15 @@ def __iter__(self): return ListIterator(self.node) def __str__(self): - return 'List({})'.format(', '.join(str(x) for x in self)) + return f'''List({', '.join(str(x) for x in self)})''' def __repr__(self): - return 'List({})'.format(', '.join(repr(x) for x in self)) + return f'''List({', '.join(repr(x) for x in self)})''' def __eq__(self, other): - return isinstance(other, LinkedList) and list(self) == list(other) + return list(self) == list(other) \ + if isinstance(other, LinkedList) \ + else NotImplemented def __ne__(self, other): return not self.__eq__(other) diff --git a/hail/python/hail/utils/struct.py b/hail/python/hail/utils/struct.py index 356edd025e6..a2ff7df7bec 100644 --- a/hail/python/hail/utils/struct.py +++ b/hail/python/hail/utils/struct.py @@ -94,7 +94,9 @@ def __str__(self): ) def __eq__(self, other): - return isinstance(other, Struct) and self._fields == other._fields + return self._fields == other._fields \ + if isinstance(other, Struct) \ + else NotImplemented def __hash__(self): return 37 + hash(tuple(sorted(self._fields.items()))) diff --git a/hail/python/test/hail/expr/test_functions.py b/hail/python/test/hail/expr/test_functions.py index c7e1a41fa2f..5019de46db7 100644 --- a/hail/python/test/hail/expr/test_functions.py +++ b/hail/python/test/hail/expr/test_functions.py @@ -85,3 +85,10 @@ def test_array(): with pytest.raises(ValueError, match='array: only one dimensional ndarrays are supported: ndarray'): hl.eval(hl.array(hl.nd.array([[1.0], [2.0]]))) + + +def test_literal_free_vars(): + "Give better error messages in response to code written by ChatGPT" + array = hl.literal([1, 2, 3]) + with pytest.raises(ValueError, match='expressions that depend on other expressions'): + array.map(hl.literal) diff --git a/hail/python/test/hail/genetics/test_call.py b/hail/python/test/hail/genetics/test_call.py index 63a0712a545..6ab0d82caa3 100644 --- a/hail/python/test/hail/genetics/test_call.py +++ b/hail/python/test/hail/genetics/test_call.py @@ -91,3 +91,10 @@ def test_zeroploid(self): "Calls with greater than 2 alleles are not supported.", Call, [1, 1, 1, 1]) + +def test_call_rich_comparison(): + val = Call([0, 0]) + expr = hl.call(0, 0) + + assert hl.eval(val == expr) + assert hl.eval(expr == val) diff --git a/hail/python/test/hail/genetics/test_locus.py b/hail/python/test/hail/genetics/test_locus.py index ebf0491aeb3..94488bd143e 100644 --- a/hail/python/test/hail/genetics/test_locus.py +++ b/hail/python/test/hail/genetics/test_locus.py @@ -1,14 +1,17 @@ -import unittest - +from hail.genetics import Locus import hail as hl -from hail.genetics import * -from ..helpers import * -class Tests(unittest.TestCase): +def test_constructor(): + l = Locus.parse('1:100') + + assert l == Locus('1', 100) + assert l == Locus(1, 100) + assert l.reference_genome == hl.default_reference() + - def test_constructor(self): - l = Locus.parse('1:100') +def test_call_rich_comparison(): + val = Locus(1, 1) + expr = hl.locus('1', 1) - self.assertEqual(l, Locus('1', 100)) - self.assertEqual(l, Locus(1, 100)) - self.assertEqual(l.reference_genome, hl.default_reference()) + assert hl.eval(val == expr) + assert hl.eval(expr == val) diff --git a/hail/python/test/hail/utils/test_utils.py b/hail/python/test/hail/utils/test_utils.py index 4cd614dec8b..61019be84f7 100644 --- a/hail/python/test/hail/utils/test_utils.py +++ b/hail/python/test/hail/utils/test_utils.py @@ -421,3 +421,22 @@ def test_hadoop_ls_negated_group(glob_tests_directory): glob_tests_directory + '/abc/ghi/?23'] actual = [x['path'] for x in hl.hadoop_ls(glob_tests_directory + '/abc/ghi/[!1]23')] assert set(actual) == set(expected) + + +def test_struct_rich_comparison(): + """Asserts comparisons between structs and struct expressions are symmetric""" + struct = hl.Struct( + locus=hl.Locus(contig=10, position=60515, reference_genome='GRCh37'), + alleles=['C', 'T'] + ) + + expr = hl.struct( + locus=hl.locus(contig='10', pos=60515, reference_genome='GRCh37'), + alleles=['C', 'T'] + ) + + assert hl.eval(struct == expr) and hl.eval(expr == struct) + assert hl.eval(struct >= expr) and hl.eval(expr >= struct) + assert hl.eval(struct <= expr) and hl.eval(expr <= struct) + assert not (hl.eval(struct < expr) or hl.eval(expr < struct)) + assert not (hl.eval(struct > expr) or hl.eval(expr > struct)) From f48a4d1e90b6dde998d30b883990de11f46fe554 Mon Sep 17 00:00:00 2001 From: jigold Date: Mon, 10 Jul 2023 15:48:07 -0400 Subject: [PATCH 010/180] [batch] Add Azure debugging information when deleting deployments (#13231) I need this extra debugging information to understand what is going on in Azure with deleted VMs still showing up in the portal with ResourceNotFound errors. Miah and Greg are running into this same problem in their deployment. My guess is what is happening is the worker is active and working fine, but then the deployment gets "Canceled" because the OMSAgent takes too long to deploy. So our loop then cancels the deployment which messes up the state in Azure of the already deployed and running VM. I popped the parameters from the deployment result in case it contains sensitive data (I'm mainly worried about any private SSH keys). --- batch/batch/cloud/azure/driver/driver.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/batch/batch/cloud/azure/driver/driver.py b/batch/batch/cloud/azure/driver/driver.py index 5f908f843b0..797a1610cc2 100644 --- a/batch/batch/cloud/azure/driver/driver.py +++ b/batch/batch/cloud/azure/driver/driver.py @@ -1,4 +1,5 @@ import asyncio +import json import logging import os @@ -184,6 +185,7 @@ async def delete_orphaned_nics(self) -> None: async for nic_name in self.resources_client.list_nic_names(self.machine_name_prefix): if self._resource_is_orphaned(nic_name): try: + log.info(f'deleting orphaned nic {nic_name}') await self.network_client.delete_nic(nic_name, ignore_not_found=True) except asyncio.CancelledError: raise @@ -195,6 +197,7 @@ async def delete_orphaned_public_ips(self) -> None: async for public_ip_name in self.resources_client.list_public_ip_names(self.machine_name_prefix): if self._resource_is_orphaned(public_ip_name): try: + log.info(f'deleting orphaned public ip {public_ip_name}') await self.network_client.delete_public_ip(public_ip_name, ignore_not_found=True) except asyncio.CancelledError: raise @@ -209,6 +212,8 @@ async def delete_completed_deployments(self) -> None: deployment_name = deployment['name'] if deployment_name.startswith(self.machine_name_prefix): try: + deployment.pop('parameters', None) + log.info(f'deleting deployment {deployment_name} {json.dumps(deployment)}') await self.arm_client.delete(f'/deployments/{deployment_name}') except asyncio.CancelledError: raise From 479ef56525eeb2a4d17da9e078dc55dfd6b30ce7 Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Tue, 11 Jul 2023 10:45:08 -0400 Subject: [PATCH 011/180] [compiler] don't force TableRead to produce a TableValue (#13229) Currently `TableRead.execute` always produces a `TableValueIntermediate`, even though almost all `TableReader`s are lowerable, so could produce a `TableStageIntermediate`. This pr refactors `TableReader` to allow producing a `TableStageIntermediate` in most cases, and to make it clearer which readers still need to be lowered (only `TableFromBlockMatrixNativeReader`, `MatrixVCFReader`, and `MatrixPLINKReader`). It also deletes some now dead code. --- .../is/hail/expr/ir/GenericTableValue.scala | 68 +------------------ .../is/hail/expr/ir/StringTableReader.scala | 9 +-- .../main/scala/is/hail/expr/ir/TableIR.scala | 29 ++++---- .../ir/lowering/LowerDistributedSort.scala | 10 --- .../expr/ir/lowering/RVDToTableStage.scala | 6 +- .../is/hail/io/avro/AvroTableReader.scala | 10 ++- .../main/scala/is/hail/io/bgen/LoadBgen.scala | 11 --- .../scala/is/hail/io/plink/LoadPlink.scala | 3 - .../main/scala/is/hail/io/vcf/LoadVCF.scala | 5 +- .../scala/is/hail/expr/ir/PruneSuite.scala | 5 +- .../scala/is/hail/expr/ir/TableIRSuite.scala | 6 +- 11 files changed, 36 insertions(+), 126 deletions(-) diff --git a/hail/src/main/scala/is/hail/expr/ir/GenericTableValue.scala b/hail/src/main/scala/is/hail/expr/ir/GenericTableValue.scala index b009fe92ab7..8ea524a2fd1 100644 --- a/hail/src/main/scala/is/hail/expr/ir/GenericTableValue.scala +++ b/hail/src/main/scala/is/hail/expr/ir/GenericTableValue.scala @@ -122,26 +122,6 @@ class PartitionIteratorLongReader( } } -class GenericTableValueRDDPartition( - val index: Int, - val context: Any -) extends Partition - -class GenericTableValueRDD( - @transient val contexts: IndexedSeq[Any], - body: (Region, HailClassLoader, Any) => Iterator[Long] -) extends RDD[RVDContext => Iterator[Long]](SparkBackend.sparkContext("GenericTableValueRDD"), Nil) { - def getPartitions: Array[Partition] = contexts.zipWithIndex.map { case (c, i) => - new GenericTableValueRDDPartition(i, c) - }.toArray - - def compute(split: Partition, context: TaskContext): Iterator[RVDContext => Iterator[Long]] = { - Iterator.single { (rvdCtx: RVDContext) => - body(rvdCtx.region, theHailClassLoaderForSparkWorkers, split.asInstanceOf[GenericTableValueRDDPartition].context) - } - } -} - abstract class LoweredTableReaderCoercer { def coerce(ctx: ExecuteContext, globals: IR, @@ -164,8 +144,8 @@ class GenericTableValue( assert(contextType.hasField("partitionIndex")) assert(contextType.fieldType("partitionIndex") == TInt32) - var ltrCoercer: LoweredTableReaderCoercer = _ - def getLTVCoercer(ctx: ExecuteContext, context: String, cacheKey: Any): LoweredTableReaderCoercer = { + private var ltrCoercer: LoweredTableReaderCoercer = _ + private def getLTVCoercer(ctx: ExecuteContext, context: String, cacheKey: Any): LoweredTableReaderCoercer = { if (ltrCoercer == null) { ltrCoercer = LoweredTableReader.makeCoercer( ctx, @@ -210,48 +190,4 @@ class GenericTableValue( requestedBody) } } - - def toContextRDD(fs: FS, requestedRowType: TStruct): ContextRDD[Long] = { - val localBody = body(requestedRowType) - ContextRDD(new GenericTableValueRDD(contexts, localBody(_, _, fs, _))) - } - - private[this] var rvdCoercer: RVDCoercer = _ - - def getRVDCoercer(ctx: ExecuteContext): RVDCoercer = { - if (rvdCoercer == null) { - rvdCoercer = RVD.makeCoercer( - ctx, - RVDType(bodyPType(fullTableType.rowType), fullTableType.key), - 1, - toContextRDD(ctx.fs, fullTableType.keyType)) - } - rvdCoercer - } - - def toTableValue(ctx: ExecuteContext, requestedType: TableType): TableValue = { - val requestedRowType = requestedType.rowType - val requestedRowPType = bodyPType(requestedType.rowType) - val crdd = toContextRDD(ctx.fs, requestedRowType) - - val rvd = partitioner match { - case Some(partitioner) => - RVD( - RVDType(requestedRowPType, fullTableType.key), - partitioner, - crdd) - case None if requestedType.key.isEmpty => - RVD( - RVDType(requestedRowPType, fullTableType.key), - RVDPartitioner.unkeyed(ctx.stateManager, contexts.length), - crdd) - case None => - getRVDCoercer(ctx).coerce(RVDType(requestedRowPType, fullTableType.key), crdd) - } - - TableValue(ctx, - requestedType, - BroadcastRow(ctx, globals(requestedType.globalType), requestedType.globalType), - rvd) - } } diff --git a/hail/src/main/scala/is/hail/expr/ir/StringTableReader.scala b/hail/src/main/scala/is/hail/expr/ir/StringTableReader.scala index 6ad351100d8..61865ed5449 100644 --- a/hail/src/main/scala/is/hail/expr/ir/StringTableReader.scala +++ b/hail/src/main/scala/is/hail/expr/ir/StringTableReader.scala @@ -3,7 +3,7 @@ import is.hail.annotations.Region import is.hail.asm4s._ import is.hail.backend.ExecuteContext import is.hail.expr.ir.functions.StringFunctions -import is.hail.expr.ir.lowering.{TableStage, TableStageDependency, TableStageToRVD} +import is.hail.expr.ir.lowering.{LowererUnsupportedOperation, TableStage, TableStageDependency, TableStageToRVD} import is.hail.expr.ir.streams.StreamProducer import is.hail.io.fs.{FS, FileStatus} import is.hail.rvd.RVDPartitioner @@ -168,11 +168,8 @@ class StringTableReader( ) } - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = { - val ts = lower(ctx, requestedType) - val (broadCastRow, rvd) = TableStageToRVD.apply(ctx, ts) - TableValue(ctx, requestedType, broadCastRow, rvd) - } + override def lowerGlobals(ctx: ExecuteContext, requestedGlobalsType: TStruct): IR = + throw new LowererUnsupportedOperation(s"${ getClass.getSimpleName }.lowerGlobals not implemented") override def partitionCounts: Option[IndexedSeq[Long]] = None diff --git a/hail/src/main/scala/is/hail/expr/ir/TableIR.scala b/hail/src/main/scala/is/hail/expr/ir/TableIR.scala index 1d6325b619d..ffff0b15c4a 100644 --- a/hail/src/main/scala/is/hail/expr/ir/TableIR.scala +++ b/hail/src/main/scala/is/hail/expr/ir/TableIR.scala @@ -481,7 +481,10 @@ trait TableReaderWithExtraUID extends TableReader { abstract class TableReader { def pathsUsed: Seq[String] - def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue + def toExecuteIntermediate(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableExecuteIntermediate = { + assert(!dropRows) + TableExecuteIntermediate(lower(ctx, requestedType)) + } def partitionCounts: Option[IndexedSeq[Long]] @@ -503,11 +506,9 @@ abstract class TableReader { StringEscapeUtils.escapeString(JsonMethods.compact(toJValue)) } - def lowerGlobals(ctx: ExecuteContext, requestedGlobalsType: TStruct): IR = - throw new LowererUnsupportedOperation(s"${ getClass.getSimpleName }.lowerGlobals not implemented") + def lowerGlobals(ctx: ExecuteContext, requestedGlobalsType: TStruct): IR - def lower(ctx: ExecuteContext, requestedType: TableType): TableStage = - throw new LowererUnsupportedOperation(s"${ getClass.getSimpleName }.lower not implemented") + def lower(ctx: ExecuteContext, requestedType: TableType): TableStage } object TableNativeReader { @@ -1409,9 +1410,6 @@ class TableNativeReader( VirtualTypeWithReq(tcoerce[PStruct](spec.globalsComponent.rvdSpec(ctx.fs, params.path) .typedCodecSpec.encodedType.decodedPType(requestedType.globalType))) - def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = - TableExecuteIntermediate(lower(ctx, requestedType)).asTableValue(ctx) - override def toJValue: JValue = { implicit val formats: Formats = DefaultFormats decomposeWithName(params, "TableNativeReader") @@ -1525,9 +1523,6 @@ case class TableNativeZippedReader( (t, mk) } - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = - TableExecuteIntermediate(lower(ctx, requestedType)).asTableValue(ctx) - override def lowerGlobals(ctx: ExecuteContext, requestedGlobalsType: TStruct): IR = { val globalsSpec = specLeft.globalsSpec val globalsPath = specLeft.globalsComponent.absolutePath(pathLeft) @@ -1612,7 +1607,7 @@ case class TableFromBlockMatrixNativeReader( override def globalRequiredness(ctx: ExecuteContext, requestedType: TableType): VirtualTypeWithReq = VirtualTypeWithReq(PCanonicalStruct.empty(required = true)) - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = { + override def toExecuteIntermediate(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableExecuteIntermediate = { val rowsRDD = new BlockMatrixReadRowBlockedRDD( ctx.fsBc, params.path, partitionRanges, requestedType.rowType, metadata, maybeMaximumCacheMemoryInBytes = params.maximumCacheMemoryInBytes) @@ -1622,9 +1617,15 @@ case class TableFromBlockMatrixNativeReader( val rowTyp = PType.canonical(requestedType.rowType, required = true).asInstanceOf[PStruct] val rvd = RVD(RVDType(rowTyp, fullType.key.filter(rowTyp.hasField)), partitioner, ContextRDD(rowsRDD)) - TableValue(ctx, requestedType, BroadcastRow.empty(ctx), rvd) + TableExecuteIntermediate(TableValue(ctx, requestedType, BroadcastRow.empty(ctx), rvd)) } + override def lower(ctx: ExecuteContext, requestedType: TableType): TableStage = + throw new LowererUnsupportedOperation(s"${ getClass.getSimpleName }.lower not implemented") + + override def lowerGlobals(ctx: ExecuteContext, requestedGlobalsType: TStruct): IR = + throw new LowererUnsupportedOperation(s"${ getClass.getSimpleName }.lowerGlobals not implemented") + override def toJValue: JValue = { decomposeWithName(params, "TableFromBlockMatrixNativeReader")(TableReader.formats) } @@ -1666,7 +1667,7 @@ case class TableRead(typ: TableType, dropRows: Boolean, tr: TableReader) extends } protected[ir] override def execute(ctx: ExecuteContext, r: LoweringAnalyses): TableExecuteIntermediate = - new TableValueIntermediate(tr.apply(ctx, typ, dropRows)) + tr.toExecuteIntermediate(ctx, typ, dropRows) } case class TableParallelize(rowsAndGlobal: IR, nPartitions: Option[Int] = None) extends TableIR { diff --git a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerDistributedSort.scala b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerDistributedSort.scala index 81c35b43e62..950faa9084d 100644 --- a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerDistributedSort.scala +++ b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerDistributedSort.scala @@ -70,11 +70,6 @@ object LowerDistributedSort { override def partitionCounts: Option[IndexedSeq[Long]] = None - def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = { - assert(!dropRows) - TableExecuteIntermediate(lower(ctx, requestedType)).asTableValue(ctx) - } - override def isDistinctlyKeyed: Boolean = false // FIXME: No default value def rowRequiredness(ctx: ExecuteContext, requestedType: TableType): VirtualTypeWithReq = { @@ -612,11 +607,6 @@ case class DistributionSortReader(key: TStruct, keyed: Boolean, spec: TypedCodec override def partitionCounts: Option[IndexedSeq[Long]] = None - def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = { - assert(!dropRows) - TableExecuteIntermediate(lower(ctx, requestedType)).asTableValue(ctx) - } - override def isDistinctlyKeyed: Boolean = false // FIXME: No default value def rowRequiredness(ctx: ExecuteContext, requestedType: TableType): VirtualTypeWithReq = { diff --git a/hail/src/main/scala/is/hail/expr/ir/lowering/RVDToTableStage.scala b/hail/src/main/scala/is/hail/expr/ir/lowering/RVDToTableStage.scala index d4adf6b0d1d..017f6488b11 100644 --- a/hail/src/main/scala/is/hail/expr/ir/lowering/RVDToTableStage.scala +++ b/hail/src/main/scala/is/hail/expr/ir/lowering/RVDToTableStage.scala @@ -28,7 +28,7 @@ case class RVDTableReader(rvd: RVD, globals: IR, rt: RTable) extends TableReader override def partitionCounts: Option[IndexedSeq[Long]] = None - def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = { + override def toExecuteIntermediate(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableExecuteIntermediate = { assert(!dropRows) val (Some(PTypeReferenceSingleCodeType(globType: PStruct)), f) = Compile[AsmFunction1RegionLong]( ctx, FastIndexedSeq(), FastIndexedSeq(classInfo[Region]), LongInfo, PruneDeadFields.upcast(ctx, globals, requestedType.globalType)) @@ -43,10 +43,10 @@ case class RVDTableReader(rvd: RVD, globals: IR, rt: RTable) extends TableReader requestedType.rowType)) val fsBc = ctx.fsBc - TableValue(ctx, requestedType, globRow, rvd.mapPartitionsWithIndex(RVDType(newRowType, requestedType.key)) { case (i, ctx, it) => + TableExecuteIntermediate(TableValue(ctx, requestedType, globRow, rvd.mapPartitionsWithIndex(RVDType(newRowType, requestedType.key)) { case (i, ctx, it) => val partF = rowF(theHailClassLoaderForSparkWorkers, fsBc.value, SparkTaskContext.get(), ctx.partitionRegion) it.map { elt => partF(ctx.r, elt) } - }) + })) } override def isDistinctlyKeyed: Boolean = false diff --git a/hail/src/main/scala/is/hail/io/avro/AvroTableReader.scala b/hail/src/main/scala/is/hail/io/avro/AvroTableReader.scala index 877976a383f..53a4a773581 100644 --- a/hail/src/main/scala/is/hail/io/avro/AvroTableReader.scala +++ b/hail/src/main/scala/is/hail/io/avro/AvroTableReader.scala @@ -2,7 +2,7 @@ package is.hail.io.avro import is.hail.backend.ExecuteContext import is.hail.expr.ir._ -import is.hail.expr.ir.lowering.{TableStage, TableStageDependency} +import is.hail.expr.ir.lowering.{LowererUnsupportedOperation, TableStage, TableStageDependency} import is.hail.rvd.RVDPartitioner import is.hail.types.physical.{PCanonicalStruct, PCanonicalTuple, PInt64Required} import is.hail.types.virtual._ @@ -44,11 +44,6 @@ class AvroTableReader( def renderShort(): String = defaultRender() - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = { - val ts = lower(ctx, requestedType) - new TableStageIntermediate(ts).asTableValue(ctx) - } - override def lower(ctx: ExecuteContext, requestedType: TableType): TableStage = { val globals = MakeStruct(FastIndexedSeq()) val contexts = zip2(ToStream(Literal(TArray(TString), paths)), StreamIota(I32(0), I32(1)), ArrayZipBehavior.TakeMinLength) { (path, idx) => @@ -64,6 +59,9 @@ class AvroTableReader( } ) } + + override def lowerGlobals(ctx: ExecuteContext, requestedGlobalsType: TStruct): IR = + throw new LowererUnsupportedOperation(s"${ getClass.getSimpleName }.lowerGlobals not implemented") } object AvroTableReader { diff --git a/hail/src/main/scala/is/hail/io/bgen/LoadBgen.scala b/hail/src/main/scala/is/hail/io/bgen/LoadBgen.scala index dc7e4dba05c..5d76f90f8e9 100644 --- a/hail/src/main/scala/is/hail/io/bgen/LoadBgen.scala +++ b/hail/src/main/scala/is/hail/io/bgen/LoadBgen.scala @@ -479,17 +479,6 @@ class MatrixBGENReader( override def globalRequiredness(ctx: ExecuteContext, requestedType: TableType): VirtualTypeWithReq = VirtualTypeWithReq(PType.canonical(requestedType.globalType, required = true)) - def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = { - - val _lc = lower(ctx, requestedType) - val lc = if (dropRows) - _lc.copy(partitioner = _lc.partitioner.copy(rangeBounds = Array[Interval]()), - contexts = StreamTake(_lc.contexts, 0)) - else _lc - - TableExecuteIntermediate(lc).asTableValue(ctx) - } - override def lowerGlobals(ctx: ExecuteContext, requestedGlobalType: TStruct): IR = { requestedGlobalType.fieldOption(LowerMatrixIR.colsFieldName) match { case Some(f) => diff --git a/hail/src/main/scala/is/hail/io/plink/LoadPlink.scala b/hail/src/main/scala/is/hail/io/plink/LoadPlink.scala index eb4fc633815..5ffbc1f43be 100644 --- a/hail/src/main/scala/is/hail/io/plink/LoadPlink.scala +++ b/hail/src/main/scala/is/hail/io/plink/LoadPlink.scala @@ -485,9 +485,6 @@ class MatrixPLINKReader( body) } - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = - executeGeneric(ctx).toTableValue(ctx, requestedType) - override def lowerGlobals(ctx: ExecuteContext, requestedGlobalsType: TStruct): IR = { val tt = fullMatrixType.toTableType(LowerMatrixIR.entriesFieldName, LowerMatrixIR.colsFieldName) val subset = tt.globalType.valueSubsetter(requestedGlobalsType) diff --git a/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala b/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala index e2cc73bf1c0..cf5801a3bfb 100644 --- a/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala +++ b/hail/src/main/scala/is/hail/io/vcf/LoadVCF.scala @@ -8,7 +8,7 @@ import is.hail.backend.{BroadcastValue, ExecuteContext, HailStateManager} import is.hail.expr.JSONAnnotationImpex import is.hail.expr.ir.lowering.TableStage import is.hail.expr.ir.streams.StreamProducer -import is.hail.expr.ir.{CloseableIterator, EmitCode, EmitCodeBuilder, EmitMethodBuilder, GenericLine, GenericLines, GenericTableValue, IEmitCode, IR, IRParser, Literal, LowerMatrixIR, MatrixHybridReader, MatrixReader, PartitionReader, TableValue} +import is.hail.expr.ir.{CloseableIterator, EmitCode, EmitCodeBuilder, EmitMethodBuilder, GenericLine, GenericLines, GenericTableValue, IEmitCode, IR, IRParser, Literal, LowerMatrixIR, MatrixHybridReader, MatrixReader, TableExecuteIntermediate, PartitionReader, TableValue} import is.hail.io.fs.{FS, FileStatus} import is.hail.io.tabix._ import is.hail.io.vcf.LoadVCF.{getHeaderLines, parseHeader} @@ -1965,9 +1965,6 @@ class MatrixVCFReader( override def lower(ctx: ExecuteContext, requestedType: TableType): TableStage = executeGeneric(ctx).toTableStage(ctx, requestedType, "VCF", params) - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = - executeGeneric(ctx, dropRows).toTableValue(ctx, requestedType) - override def toJValue: JValue = { implicit val formats: Formats = DefaultFormats decomposeWithName(params, "MatrixVCFReader") diff --git a/hail/src/test/scala/is/hail/expr/ir/PruneSuite.scala b/hail/src/test/scala/is/hail/expr/ir/PruneSuite.scala index 334d4262139..8e2e460e567 100644 --- a/hail/src/test/scala/is/hail/expr/ir/PruneSuite.scala +++ b/hail/src/test/scala/is/hail/expr/ir/PruneSuite.scala @@ -3,6 +3,7 @@ package is.hail.expr.ir import is.hail.HailSuite import is.hail.backend.ExecuteContext import is.hail.expr.Nat +import is.hail.expr.ir.lowering.TableStage import is.hail.methods.{ForceCountMatrixTable, ForceCountTable} import is.hail.rvd.RVD import is.hail.types._ @@ -114,7 +115,9 @@ class PruneSuite extends HailSuite { def pathsUsed: IndexedSeq[String] = FastSeq() - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = ??? + override def lower(ctx: ExecuteContext, requestedType: TableType): TableStage = ??? + + override def lowerGlobals(ctx: ExecuteContext, requestedType: TStruct): IR = ??? def partitionCounts: Option[IndexedSeq[Long]] = ??? diff --git a/hail/src/test/scala/is/hail/expr/ir/TableIRSuite.scala b/hail/src/test/scala/is/hail/expr/ir/TableIRSuite.scala index 7dad5ce6e70..9d7b0c9b73f 100644 --- a/hail/src/test/scala/is/hail/expr/ir/TableIRSuite.scala +++ b/hail/src/test/scala/is/hail/expr/ir/TableIRSuite.scala @@ -6,7 +6,7 @@ import is.hail.annotations.SafeNDArray import is.hail.backend.ExecuteContext import is.hail.expr.Nat import is.hail.expr.ir.TestUtils._ -import is.hail.expr.ir.lowering.{DArrayLowering, LowerTableIR} +import is.hail.expr.ir.lowering.{DArrayLowering, LowerTableIR, TableStage} import is.hail.methods.ForceCountTable import is.hail.rvd.RVDPartitioner import is.hail.types._ @@ -826,7 +826,9 @@ class TableIRSuite extends HailSuite { def pathsUsed: Seq[String] = FastSeq() - override def apply(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableValue = ??? + override def lower(ctx: ExecuteContext, requestedType: TableType): TableStage = ??? + + override def lowerGlobals(ctx: ExecuteContext, requestedType: TStruct): IR = ??? override def partitionCounts: Option[IndexedSeq[Long]] = Some(FastIndexedSeq(1, 2, 3, 4)) From 39a9de0006f98f75e04b21fffa0b2e279851f022 Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 11 Jul 2023 12:31:24 -0400 Subject: [PATCH 012/180] [batch] Add new list_batches query interface to REST calls (#13199) This is stacked on #12748 --- batch/batch/front_end/front_end.py | 237 ++++------ batch/batch/front_end/query/__init__.py | 19 +- batch/batch/front_end/query/query.py | 413 ++++++++++++++---- batch/batch/front_end/query/query_v1.py | 127 +++++- batch/batch/front_end/query/query_v2.py | 203 +++++++-- batch/sql/add-list-batches-index.sql | 1 + batch/sql/estimated-current.sql | 1 + batch/test/test_batch.py | 231 +++++++++- build.yaml | 3 + hail/python/hailtop/batch_client/aioclient.py | 9 +- hail/python/hailtop/batch_client/client.py | 4 +- 11 files changed, 964 insertions(+), 284 deletions(-) create mode 100644 batch/sql/add-list-batches-index.sql diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index e8972d258c3..dc943128b44 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -88,7 +88,13 @@ regions_to_bits_rep, unavailable_if_frozen, ) -from .query import CURRENT_QUERY_VERSION, build_batch_jobs_query +from .query import ( + CURRENT_QUERY_VERSION, + parse_batch_jobs_query_v1, + parse_batch_jobs_query_v2, + parse_list_batches_query_v1, + parse_list_batches_query_v2, +) from .validate import ValidationError, validate_and_clean_jobs, validate_batch, validate_batch_update uvloop.install() @@ -206,20 +212,19 @@ async def rest_get_supported_regions(request, userdata): # pylint: disable=unus async def _handle_ui_error(session, f, *args, **kwargs): try: - await f(*args, **kwargs) + return await f(*args, **kwargs) except KeyError as e: set_message(session, str(e), 'error') log.info(f'ui error: KeyError {e}') - return True + raise except BatchOperationAlreadyCompletedError as e: set_message(session, e.message, e.ui_error_type) log.info(f'ui error: BatchOperationAlreadyCompletedError {e.message}') - return True + raise except BatchUserError as e: set_message(session, e.message, e.ui_error_type) log.info(f'ui error: BatchUserError {e.message}') - return True - return False + raise async def _handle_api_error(f, *args, **kwargs): @@ -234,7 +239,11 @@ async def _handle_api_error(f, *args, **kwargs): async def _query_batch_jobs(request, batch_id: int, version: int, q: str, last_job_id: Optional[int]): db: Database = request.app['db'] - sql, sql_args = build_batch_jobs_query(batch_id, version, q, last_job_id) + if version == 1: + sql, sql_args = parse_batch_jobs_query_v1(batch_id, q, last_job_id) + else: + assert version == 2, version + sql, sql_args = parse_batch_jobs_query_v2(batch_id, q, last_job_id) jobs = [job_record_to_dict(record, record['name']) async for record in db.select_and_fetchall(sql, sql_args)] @@ -600,127 +609,15 @@ async def rest_get_job_container_log(request, userdata, batch_id): # pylint: di return await get_job_container_log(request, batch_id) -async def _query_batches(request, user, q): - db = request.app['db'] - - where_conditions = [ - '(billing_project_users.`user` = %s AND billing_project_users.billing_project = batches.billing_project)', - 'NOT deleted', - ] - where_args = [user] - - last_batch_id = request.query.get('last_batch_id') - if last_batch_id is not None: - last_batch_id = int(last_batch_id) - where_conditions.append('(batches.id < %s)') - where_args.append(last_batch_id) - - terms = q.split() - for _t in terms: - if _t[0] == '!': - negate = True - t = _t[1:] - else: - negate = False - t = _t - - if '=' in t: - k, v = t.split('=', 1) - condition = ''' -((batches.id) IN - (SELECT batch_id FROM batch_attributes - WHERE `key` = %s AND `value` = %s)) -''' - args = [k, v] - elif t.startswith('has:'): - k = t[4:] - condition = ''' -((batches.id) IN - (SELECT batch_id FROM batch_attributes - WHERE `key` = %s)) -''' - args = [k] - elif t.startswith('user:'): - k = t[5:] - condition = ''' -(batches.`user` = %s) -''' - args = [k] - elif t.startswith('billing_project:'): - k = t[16:] - condition = ''' -(billing_projects.name_cs = %s) -''' - args = [k] - elif t == 'open': - condition = "(`state` = 'open')" - args = [] - elif t == 'closed': - condition = "(`state` != 'open')" - args = [] - elif t == 'complete': - condition = "(`state` = 'complete')" - args = [] - elif t == 'running': - condition = "(`state` = 'running')" - args = [] - elif t == 'cancelled': - condition = '(batches_cancelled.id IS NOT NULL)' - args = [] - elif t == 'failure': - condition = '(n_failed > 0)' - args = [] - elif t == 'success': - # need complete because there might be no jobs - condition = "(`state` = 'complete' AND n_succeeded = n_jobs)" - args = [] - else: - session = await aiohttp_session.get_session(request) - set_message(session, f'Invalid search term: {t}.', 'error') - return ([], None) - - if negate: - condition = f'(NOT {condition})' - - where_conditions.append(condition) - where_args.extend(args) - - sql = f''' -WITH base_t AS ( - SELECT batches.*, - batches_cancelled.id IS NOT NULL AS cancelled, - batches_n_jobs_in_complete_states.n_completed, - batches_n_jobs_in_complete_states.n_succeeded, - batches_n_jobs_in_complete_states.n_failed, - batches_n_jobs_in_complete_states.n_cancelled - FROM batches - LEFT JOIN billing_projects ON batches.billing_project = billing_projects.name - LEFT JOIN batches_n_jobs_in_complete_states - ON batches.id = batches_n_jobs_in_complete_states.id - LEFT JOIN batches_cancelled - ON batches.id = batches_cancelled.id - STRAIGHT_JOIN billing_project_users ON batches.billing_project = billing_project_users.billing_project - WHERE {' AND '.join(where_conditions)} - ORDER BY id DESC - LIMIT 51 -) -SELECT base_t.*, COALESCE(SUM(`usage` * rate), 0) AS cost -FROM base_t -LEFT JOIN ( - SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM base_t - LEFT JOIN aggregated_batch_resources_v2 ON base_t.id = aggregated_batch_resources_v2.batch_id - GROUP BY batch_id, resource_id -) AS usage_t ON base_t.id = usage_t.batch_id -LEFT JOIN resources ON usage_t.resource_id = resources.resource_id -GROUP BY id -ORDER BY id DESC; -''' - sql_args = where_args +async def _query_batches(request, user: str, q: str, version: int, last_batch_id: Optional[int]): + db: Database = request.app['db'] + if version == 1: + sql, sql_args = parse_list_batches_query_v1(user, q, last_batch_id) + else: + assert version == 2, version + sql, sql_args = parse_list_batches_query_v2(user, q, last_batch_id) - batches = [ - batch_record_to_dict(batch) async for batch in db.select_and_fetchall(sql, sql_args, query_name='get_batches') - ] + batches = [batch_record_to_dict(record) async for record in db.select_and_fetchall(sql, sql_args)] if len(batches) == 51: batches.pop() @@ -734,10 +631,25 @@ async def _query_batches(request, user, q): @routes.get('/api/v1alpha/batches') @auth.rest_authenticated_users_only @add_metadata_to_request -async def get_batches(request, userdata): # pylint: disable=unused-argument +async def get_batches_v1(request, userdata): # pylint: disable=unused-argument user = userdata['username'] q = request.query.get('q', f'user:{user}') - batches, last_batch_id = await _query_batches(request, user, q) + last_batch_id = request.query.get('last_batch_id') + batches, last_batch_id = await _handle_api_error(_query_batches, request, user, q, 1, last_batch_id) + body = {'batches': batches} + if last_batch_id is not None: + body['last_batch_id'] = last_batch_id + return json_response(body) + + +@routes.get('/api/v2alpha/batches') +@auth.rest_authenticated_users_only +@add_metadata_to_request +async def get_batches_v2(request, userdata): # pylint: disable=unused-argument + user = userdata['username'] + q = request.query.get('q', f'user = {user}') + last_batch_id = request.query.get('last_batch_id') + batches, last_batch_id = await _handle_api_error(_query_batches, request, user, q, 2, last_batch_id) body = {'batches': batches} if last_batch_id is not None: body['last_batch_id'] = last_batch_id @@ -1757,11 +1669,12 @@ async def ui_cancel_batch(request, userdata, batch_id): # pylint: disable=unuse if q is not None: params['q'] = q session = await aiohttp_session.get_session(request) - errored = await _handle_ui_error(session, _cancel_batch, request.app, batch_id) - if not errored: + try: + await _handle_ui_error(session, _cancel_batch, request.app, batch_id) set_message(session, f'Batch {batch_id} cancelled.', 'info') - location = request.app.router['batches'].url_for().with_query(params) - return web.HTTPFound(location=location) + finally: + location = request.app.router['batches'].url_for().with_query(params) + return web.HTTPFound(location=location) # pylint: disable=lost-exception @routes.post('/batches/{batch_id}/delete') @@ -1785,11 +1698,24 @@ async def ui_delete_batch(request, userdata, batch_id): # pylint: disable=unuse @auth.web_authenticated_users_only() @catch_ui_error_in_dev async def ui_batches(request, userdata): + session = await aiohttp_session.get_session(request) user = userdata['username'] q = request.query.get('q', f'user:{user}') - batches, last_batch_id = await _query_batches(request, user, q) + last_batch_id = request.query.get('last_batch_id') + if last_batch_id is not None: + last_batch_id = int(last_batch_id) + try: + batches, last_batch_id = await _handle_ui_error( + session, _query_batches, request, user, q, CURRENT_QUERY_VERSION, last_batch_id + ) + except asyncio.CancelledError: + raise + except Exception: + batches = [] + for batch in batches: batch['cost'] = cost_str(batch['cost']) + page_context = {'batches': batches, 'q': q, 'last_batch_id': last_batch_id} return await render_template('batch', request, userdata, 'batches.html', page_context) @@ -2328,10 +2254,11 @@ async def post_edit_billing_limits_ui(request, userdata): # pylint: disable=unu post = await request.post() limit = post['limit'] session = await aiohttp_session.get_session(request) - errored = await _handle_ui_error(session, _edit_billing_limit, db, billing_project, limit) - if not errored: + try: + await _handle_ui_error(session, _edit_billing_limit, db, billing_project, limit) set_message(session, f'Modified limit {limit} for billing project {billing_project}.', 'info') - return web.HTTPFound(deploy_config.external_url('batch', '/billing_limits')) + finally: + return web.HTTPFound(deploy_config.external_url('batch', '/billing_limits')) # pylint: disable=lost-exception async def _query_billing(request, user=None): @@ -2553,10 +2480,11 @@ async def post_billing_projects_remove_user(request, userdata): # pylint: disab user = request.match_info['user'] session = await aiohttp_session.get_session(request) - errored = await _handle_ui_error(session, _remove_user_from_billing_project, db, billing_project, user) - if not errored: + try: + await _handle_ui_error(session, _remove_user_from_billing_project, db, billing_project, user) set_message(session, f'Removed user {user} from billing project {billing_project}.', 'info') - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) + finally: + return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/users/{user}/remove') @@ -2624,10 +2552,11 @@ async def post_billing_projects_add_user(request, userdata): # pylint: disable= session = await aiohttp_session.get_session(request) - errored = await _handle_ui_error(session, _add_user_to_billing_project, db, billing_project, user) - if not errored: + try: + await _handle_ui_error(session, _add_user_to_billing_project, db, billing_project, user) set_message(session, f'Added user {user} to billing project {billing_project}.', 'info') - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) + finally: + return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/users/{user}/add') @@ -2679,11 +2608,11 @@ async def post_create_billing_projects(request, userdata): # pylint: disable=un billing_project = post['billing_project'] session = await aiohttp_session.get_session(request) - errored = await _handle_ui_error(session, _create_billing_project, db, billing_project) - if not errored: + try: + await _handle_ui_error(session, _create_billing_project, db, billing_project) set_message(session, f'Added billing project {billing_project}.', 'info') - - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) + finally: + return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/create') @@ -2739,10 +2668,11 @@ async def post_close_billing_projects(request, userdata): # pylint: disable=unu billing_project = request.match_info['billing_project'] session = await aiohttp_session.get_session(request) - errored = await _handle_ui_error(session, _close_billing_project, db, billing_project) - if not errored: + try: + await _handle_ui_error(session, _close_billing_project, db, billing_project) set_message(session, f'Closed billing project {billing_project}.', 'info') - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) + finally: + return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/close') @@ -2783,10 +2713,11 @@ async def post_reopen_billing_projects(request, userdata): # pylint: disable=un billing_project = request.match_info['billing_project'] session = await aiohttp_session.get_session(request) - errored = await _handle_ui_error(session, _reopen_billing_project, db, billing_project) - if not errored: + try: + await _handle_ui_error(session, _reopen_billing_project, db, billing_project) set_message(session, f'Re-opened billing project {billing_project}.', 'info') - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) + finally: + return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/reopen') diff --git a/batch/batch/front_end/query/__init__.py b/batch/batch/front_end/query/__init__.py index 61dfdc7459e..c995cc378b3 100644 --- a/batch/batch/front_end/query/__init__.py +++ b/batch/batch/front_end/query/__init__.py @@ -1,13 +1,12 @@ -from typing import Optional - -from .query_v1 import parse_batch_jobs_query_v1 -from .query_v2 import parse_batch_jobs_query_v2 +from .query_v1 import parse_batch_jobs_query_v1, parse_list_batches_query_v1 +from .query_v2 import parse_batch_jobs_query_v2, parse_list_batches_query_v2 CURRENT_QUERY_VERSION = 1 - -def build_batch_jobs_query(batch_id: int, version: int, q: str, last_job_id: Optional[int]): - if version == 1: - return parse_batch_jobs_query_v1(batch_id, q, last_job_id) - assert version == 2, version - return parse_batch_jobs_query_v2(batch_id, q, last_job_id) +__all__ = [ + 'CURRENT_QUERY_VERSION', + 'parse_batch_jobs_query_v1', + 'parse_batch_jobs_query_v2', + 'parse_list_batches_query_v1', + 'parse_list_batches_query_v2', +] diff --git a/batch/batch/front_end/query/query.py b/batch/batch/front_end/query/query.py index a2edb70d1ae..feaaf38e347 100644 --- a/batch/batch/front_end/query/query.py +++ b/batch/batch/front_end/query/query.py @@ -15,32 +15,6 @@ ) -class State(Enum): - PENDING = 'Pending' - READY = 'Ready' - CREATING = 'Creating' - RUNNING = 'Running' - CANCELLED = 'Cancelled' - ERROR = 'Error' - FAILED = 'Failed' - SUCCESS = 'Success' - - -state_search_term_to_states = { - 'pending': [State.PENDING], - 'ready': [State.READY], - 'creating': [State.CREATING], - 'running': [State.RUNNING], - 'live': [State.READY, State.CREATING, State.RUNNING], - 'cancelled': [State.CANCELLED], - 'error': [State.ERROR], - 'failed': [State.FAILED], - 'bad': [State.ERROR, State.FAILED], - 'success': [State.SUCCESS], - 'done': [State.CANCELLED, State.ERROR, State.FAILED, State.SUCCESS], -} - - def parse_int(word: str) -> int: try: return int(word) @@ -73,22 +47,48 @@ def query(self) -> Tuple[str, List[Any]]: raise NotImplementedError -class StateQuery(Query): +class JobState(Enum): + PENDING = 'Pending' + READY = 'Ready' + CREATING = 'Creating' + RUNNING = 'Running' + CANCELLED = 'Cancelled' + ERROR = 'Error' + FAILED = 'Failed' + SUCCESS = 'Success' + + +job_state_search_term_to_states = { + 'pending': [JobState.PENDING], + 'ready': [JobState.READY], + 'creating': [JobState.CREATING], + 'running': [JobState.RUNNING], + 'live': [JobState.READY, JobState.CREATING, JobState.RUNNING], + 'cancelled': [JobState.CANCELLED], + 'error': [JobState.ERROR], + 'failed': [JobState.FAILED], + 'bad': [JobState.ERROR, JobState.FAILED], + 'success': [JobState.SUCCESS], + 'done': [JobState.CANCELLED, JobState.ERROR, JobState.FAILED, JobState.SUCCESS], +} + + +class JobStateQuery(Query): @staticmethod - def parse(op: str, state: str) -> 'StateQuery': + def parse(op: str, state: str) -> 'JobStateQuery': operator = get_operator(op) if not isinstance(operator, ExactMatchOperator): raise QueryError(f'unexpected operator "{op}" expected one of {ExactMatchOperator.symbols}') - if state not in state_search_term_to_states: + if state not in job_state_search_term_to_states: raise QueryError(f'unknown state "{state}"') - return StateQuery(state, operator) + return JobStateQuery(state, operator) def __init__(self, state: str, operator: ExactMatchOperator): self.state = state self.operator = operator - def query(self) -> Tuple[str, List[Any]]: - states = [s.value for s in state_search_term_to_states[self.state]] + def query(self) -> Tuple[str, List[str]]: + states = [s.value for s in job_state_search_term_to_states[self.state]] condition = ' OR '.join(['(jobs.state = %s)' for _ in states]) condition = f'({condition})' if isinstance(self.operator, NotEqualExactMatchOperator): @@ -109,24 +109,24 @@ def __init__(self, job_id: int, operator: ComparisonOperator): self.job_id = job_id self.operator = operator - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[int]]: op = self.operator.to_sql() return (f'(jobs.job_id {op} %s)', [self.job_id]) -class InstanceQuery(Query): +class JobInstanceQuery(Query): @staticmethod - def parse(op: str, instance: str) -> 'InstanceQuery': + def parse(op: str, instance: str) -> 'JobInstanceQuery': operator = get_operator(op) if not isinstance(operator, MatchOperator): raise QueryError(f'unexpected operator "{op}" expected one of {MatchOperator.symbols}') - return InstanceQuery(instance, operator) + return JobInstanceQuery(instance, operator) def __init__(self, instance: str, operator: MatchOperator): self.instance = instance self.operator = operator - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[str]]: op = self.operator.to_sql() if isinstance(self.operator, PartialMatchOperator): self.instance = f'%{self.instance}%' @@ -138,19 +138,19 @@ def query(self) -> Tuple[str, List[Any]]: return (sql, [self.instance]) -class InstanceCollectionQuery(Query): +class JobInstanceCollectionQuery(Query): @staticmethod - def parse(op: str, instance_collection: str) -> 'InstanceCollectionQuery': + def parse(op: str, instance_collection: str) -> 'JobInstanceCollectionQuery': operator = get_operator(op) if not isinstance(operator, MatchOperator): raise QueryError(f'unexpected operator "{op}" expected one of {MatchOperator.symbols}') - return InstanceCollectionQuery(instance_collection, operator) + return JobInstanceCollectionQuery(instance_collection, operator) def __init__(self, inst_coll: str, operator: MatchOperator): self.inst_coll = inst_coll self.operator = operator - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[str]]: op = self.operator.to_sql() if isinstance(self.operator, PartialMatchOperator): self.inst_coll = f'%{self.inst_coll}%' @@ -158,19 +158,19 @@ def query(self) -> Tuple[str, List[Any]]: return (sql, [self.inst_coll]) -class QuotedExactMatchQuery(Query): +class JobQuotedExactMatchQuery(Query): @staticmethod - def parse(term: str) -> 'QuotedExactMatchQuery': + def parse(term: str) -> 'JobQuotedExactMatchQuery': if len(term) < 3: raise QueryError(f'expected a string of minimum length 3. Found {term}') if term[-1] != '"': raise QueryError("expected the last character of the string to be '\"'") - return QuotedExactMatchQuery(term[1:-1]) + return JobQuotedExactMatchQuery(term[1:-1]) def __init__(self, term: str): self.term = term - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[str]]: sql = ''' (((jobs.batch_id, jobs.job_id) IN (SELECT batch_id, job_id FROM job_attributes @@ -182,21 +182,21 @@ def query(self) -> Tuple[str, List[Any]]: return (sql, [self.term, self.term, self.term]) -class UnquotedPartialMatchQuery(Query): +class JobUnquotedPartialMatchQuery(Query): @staticmethod - def parse(term: str) -> 'UnquotedPartialMatchQuery': + def parse(term: str) -> 'JobUnquotedPartialMatchQuery': if len(term) < 1: raise QueryError(f'expected a string of minimum length 1. Found {term}') if term[0] == '"': raise QueryError("expected the first character of the string to not be '\"'") if term[-1] == '"': raise QueryError("expected the last character of the string to not be '\"'") - return UnquotedPartialMatchQuery(term) + return JobUnquotedPartialMatchQuery(term) def __init__(self, term: str): self.term = term - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[str]]: sql = ''' (((jobs.batch_id, jobs.job_id) IN (SELECT batch_id, job_id FROM job_attributes @@ -209,45 +209,46 @@ def query(self) -> Tuple[str, List[Any]]: return (sql, [escaped_term, escaped_term, escaped_term]) -class KeywordQuery(Query): +class JobKeywordQuery(Query): @staticmethod - def parse(op: str, key: str, value: str) -> 'KeywordQuery': + def parse(op: str, key: str, value: str) -> 'JobKeywordQuery': operator = get_operator(op) if not isinstance(operator, MatchOperator): raise QueryError(f'unexpected operator "{op}" expected one of {MatchOperator.symbols}') - return KeywordQuery(operator, key, value) + return JobKeywordQuery(operator, key, value) def __init__(self, operator: MatchOperator, key: str, value: str): self.operator = operator self.key = key self.value = value - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[str]]: op = self.operator.to_sql() + value = self.value if isinstance(self.operator, PartialMatchOperator): - self.value = f'%{self.value}%' + value = f'%{value}%' sql = f''' ((jobs.batch_id, jobs.job_id) IN (SELECT batch_id, job_id FROM job_attributes WHERE `key` = %s AND `value` {op} %s)) ''' - return (sql, [self.key, self.value]) + return (sql, [self.key, value]) -class StartTimeQuery(Query): +class JobStartTimeQuery(Query): @staticmethod - def parse(op: str, time: str) -> 'StartTimeQuery': + def parse(op: str, time: str) -> 'JobStartTimeQuery': operator = get_operator(op) if not isinstance(operator, ComparisonOperator): raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') time_msecs = parse_date(time) - return StartTimeQuery(operator, time_msecs) + return JobStartTimeQuery(operator, time_msecs) def __init__(self, operator: ComparisonOperator, time_msecs: int): self.operator = operator self.time_msecs = time_msecs - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[int]]: op = self.operator.to_sql() sql = f''' ((jobs.batch_id, jobs.job_id) IN @@ -257,20 +258,20 @@ def query(self) -> Tuple[str, List[Any]]: return (sql, [self.time_msecs]) -class EndTimeQuery(Query): +class JobEndTimeQuery(Query): @staticmethod - def parse(op: str, time: str) -> 'EndTimeQuery': + def parse(op: str, time: str) -> 'JobEndTimeQuery': operator = get_operator(op) if not isinstance(operator, ComparisonOperator): raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') time_msecs = parse_date(time) - return EndTimeQuery(operator, time_msecs) + return JobEndTimeQuery(operator, time_msecs) def __init__(self, operator: ComparisonOperator, time_msecs: int): self.operator = operator self.time_msecs = time_msecs - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[int]]: op = self.operator.to_sql() sql = f''' ((jobs.batch_id, jobs.job_id) IN @@ -280,20 +281,20 @@ def query(self) -> Tuple[str, List[Any]]: return (sql, [self.time_msecs]) -class DurationQuery(Query): +class JobDurationQuery(Query): @staticmethod - def parse(op: str, time: str) -> 'DurationQuery': + def parse(op: str, time: str) -> 'JobDurationQuery': operator = get_operator(op) if not isinstance(operator, ComparisonOperator): raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') - time_msecs = int(parse_float(time) * 1000 + 1) - return DurationQuery(operator, time_msecs) + time_msecs = int(parse_float(time) * 1000) + return JobDurationQuery(operator, time_msecs) def __init__(self, operator: ComparisonOperator, time_msecs: int): self.operator = operator self.time_msecs = time_msecs - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[int]]: op = self.operator.to_sql() sql = f''' ((jobs.batch_id, jobs.job_id) IN @@ -303,19 +304,285 @@ def query(self) -> Tuple[str, List[Any]]: return (sql, [self.time_msecs]) -class CostQuery(Query): +class JobCostQuery(Query): @staticmethod - def parse(op: str, cost_str: str) -> 'CostQuery': + def parse(op: str, cost_str: str) -> 'JobCostQuery': operator = get_operator(op) if not isinstance(operator, ComparisonOperator): raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') - cost = parse_float(cost_str) - return CostQuery(operator, cost) + cost = parse_cost(cost_str) + return JobCostQuery(operator, cost) def __init__(self, operator: ComparisonOperator, cost: float): self.operator = operator self.cost = cost - def query(self) -> Tuple[str, List[Any]]: + def query(self) -> Tuple[str, List[float]]: op = self.operator.to_sql() return (f'(cost {op} %s)', [self.cost]) + + +class BatchState(Enum): + OPEN = 'open' + CLOSED = 'closed' + COMPLETE = 'complete' + RUNNING = 'running' + CANCELLED = 'cancelled' + FAILURE = 'failure' + SUCCESS = 'success' + + +batch_state_search_term_to_state = { + 'open': BatchState.OPEN, + 'closed': BatchState.CLOSED, + 'complete': BatchState.COMPLETE, + 'running': BatchState.RUNNING, + 'cancelled': BatchState.CANCELLED, + 'failure': BatchState.FAILURE, + 'success': BatchState.SUCCESS, +} + + +class BatchStateQuery(Query): + @staticmethod + def parse(op: str, maybe_state: str) -> 'BatchStateQuery': + operator = get_operator(op) + if not isinstance(operator, ExactMatchOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ExactMatchOperator.symbols}') + if maybe_state not in batch_state_search_term_to_state: + raise QueryError(f'unknown state "{maybe_state}"') + state = batch_state_search_term_to_state[maybe_state] + return BatchStateQuery(state, operator) + + def __init__(self, state: BatchState, operator: ExactMatchOperator): + self.state = state + self.operator = operator + + def query(self) -> Tuple[str, List[Any]]: + args: List[Any] + if self.state == BatchState.OPEN: + condition = "(`state` = 'open')" + args = [] + elif self.state == BatchState.CLOSED: + condition = "(`state` != 'open')" + args = [] + elif self.state == BatchState.COMPLETE: + condition = "(`state` = 'complete')" + args = [] + elif self.state == BatchState.RUNNING: + condition = "(`state` = 'running')" + args = [] + elif self.state == BatchState.CANCELLED: + condition = '(batches_cancelled.id IS NOT NULL)' + args = [] + elif self.state == BatchState.FAILURE: + condition = '(n_failed > 0)' + args = [] + else: + assert self.state == BatchState.SUCCESS + # need complete because there might be no jobs + condition = "(`state` = 'complete' AND n_succeeded = n_jobs)" + args = [] + + if isinstance(self.operator, NotEqualExactMatchOperator): + condition = f'(NOT {condition})' + + return (condition, args) + + +class BatchIdQuery(Query): + @staticmethod + def parse(op: str, maybe_batch_id: str) -> 'BatchIdQuery': + operator = get_operator(op) + if not isinstance(operator, ComparisonOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') + batch_id = parse_int(maybe_batch_id) + return BatchIdQuery(batch_id, operator) + + def __init__(self, batch_id: int, operator: ComparisonOperator): + self.batch_id = batch_id + self.operator = operator + + def query(self) -> Tuple[str, List[int]]: + op = self.operator.to_sql() + return (f'(batches.id {op} %s)', [self.batch_id]) + + +class BatchUserQuery(Query): + @staticmethod + def parse(op: str, user: str) -> 'BatchUserQuery': + operator = get_operator(op) + if not isinstance(operator, ExactMatchOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ExactMatchOperator.symbols}') + return BatchUserQuery(user, operator) + + def __init__(self, user: str, operator: ExactMatchOperator): + self.user = user + self.operator = operator + + def query(self) -> Tuple[str, List[str]]: + op = self.operator.to_sql() + return (f'(batches.user {op} %s)', [self.user]) + + +class BatchBillingProjectQuery(Query): + @staticmethod + def parse(op: str, billing_project: str) -> 'BatchBillingProjectQuery': + operator = get_operator(op) + if not isinstance(operator, ExactMatchOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ExactMatchOperator.symbols}') + return BatchBillingProjectQuery(billing_project, operator) + + def __init__(self, billing_project: str, operator: ExactMatchOperator): + self.billing_project = billing_project + self.operator = operator + + def query(self) -> Tuple[str, List[str]]: + op = self.operator.to_sql() + return (f'(batches.billing_project {op} %s)', [self.billing_project]) + + +class BatchQuotedExactMatchQuery(Query): + @staticmethod + def parse(term: str) -> 'BatchQuotedExactMatchQuery': + if len(term) < 3: + raise QueryError(f'expected a string of minimum length 3. Found {term}') + if term[-1] != '"': + raise QueryError("expected the last character of the string to be '\"'") + return BatchQuotedExactMatchQuery(term[1:-1]) + + def __init__(self, term: str): + self.term = term + + def query(self) -> Tuple[str, List[str]]: + sql = ''' +((batches.id) IN + (SELECT batch_id FROM batch_attributes + WHERE `key` = %s OR `value` = %s)) +''' + return (sql, [self.term, self.term]) + + +class BatchUnquotedPartialMatchQuery(Query): + @staticmethod + def parse(term: str) -> 'BatchUnquotedPartialMatchQuery': + if len(term) < 1: + raise QueryError(f'expected a string of minimum length 1. Found {term}') + if term[0] == '"': + raise QueryError("expected the first character of the string to not be '\"'") + if term[-1] == '"': + raise QueryError("expected the last character of the string to not be '\"'") + return BatchUnquotedPartialMatchQuery(term) + + def __init__(self, term: str): + self.term = term + + def query(self) -> Tuple[str, List[str]]: + sql = ''' +((batches.id) IN + (SELECT batch_id FROM batch_attributes + WHERE `key` LIKE %s OR `value` LIKE %s)) +''' + escaped_term = f'%{self.term}%' + return (sql, [escaped_term, escaped_term]) + + +class BatchKeywordQuery(Query): + @staticmethod + def parse(op: str, key: str, value: str) -> 'BatchKeywordQuery': + operator = get_operator(op) + if not isinstance(operator, MatchOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {MatchOperator.symbols}') + return BatchKeywordQuery(operator, key, value) + + def __init__(self, operator: MatchOperator, key: str, value: str): + self.operator = operator + self.key = key + self.value = value + + def query(self) -> Tuple[str, List[str]]: + op = self.operator.to_sql() + value = self.value + if isinstance(self.operator, PartialMatchOperator): + value = f'%{value}%' + sql = f''' +((batches.id) IN + (SELECT batch_id FROM batch_attributes + WHERE `key` = %s AND `value` {op} %s)) + ''' + return (sql, [self.key, value]) + + +class BatchStartTimeQuery(Query): + @staticmethod + def parse(op: str, time: str) -> 'BatchStartTimeQuery': + operator = get_operator(op) + if not isinstance(operator, ComparisonOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') + time_msecs = parse_date(time) + return BatchStartTimeQuery(operator, time_msecs) + + def __init__(self, operator: ComparisonOperator, time_msecs: int): + self.operator = operator + self.time_msecs = time_msecs + + def query(self) -> Tuple[str, List[int]]: + op = self.operator.to_sql() + sql = f'(batches.time_created {op} %s)' + return (sql, [self.time_msecs]) + + +class BatchEndTimeQuery(Query): + @staticmethod + def parse(op: str, time: str) -> 'BatchEndTimeQuery': + operator = get_operator(op) + if not isinstance(operator, ComparisonOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') + time_msecs = parse_date(time) + return BatchEndTimeQuery(operator, time_msecs) + + def __init__(self, operator: ComparisonOperator, time_msecs: int): + self.operator = operator + self.time_msecs = time_msecs + + def query(self) -> Tuple[str, List[int]]: + op = self.operator.to_sql() + sql = f'(batches.time_completed {op} %s)' + return (sql, [self.time_msecs]) + + +class BatchDurationQuery(Query): + @staticmethod + def parse(op: str, time: str) -> 'BatchDurationQuery': + operator = get_operator(op) + if not isinstance(operator, ComparisonOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') + time_msecs = int(parse_float(time) * 1000) + return BatchDurationQuery(operator, time_msecs) + + def __init__(self, operator: ComparisonOperator, time_msecs: int): + self.operator = operator + self.time_msecs = time_msecs + + def query(self) -> Tuple[str, List[int]]: + op = self.operator.to_sql() + sql = f'((batches.time_completed - batches.time_created) {op} %s)' + return (sql, [self.time_msecs]) + + +class BatchCostQuery(Query): + @staticmethod + def parse(op: str, cost_str: str) -> 'BatchCostQuery': + operator = get_operator(op) + if not isinstance(operator, ComparisonOperator): + raise QueryError(f'unexpected operator "{op}" expected one of {ComparisonOperator.symbols}') + cost = parse_cost(cost_str) + return BatchCostQuery(operator, cost) + + def __init__(self, operator: ComparisonOperator, cost: float): + self.operator = operator + self.cost = cost + + def query(self) -> Tuple[str, List[float]]: + op = self.operator.to_sql() + return (f'(cost_t.cost {op} %s)', [self.cost]) diff --git a/batch/batch/front_end/query/query_v1.py b/batch/batch/front_end/query/query_v1.py index 37536e5cfe3..2833bb216d8 100644 --- a/batch/batch/front_end/query/query_v1.py +++ b/batch/batch/front_end/query/query_v1.py @@ -1,10 +1,124 @@ -from typing import Any, List, Optional +from typing import Any, List, Optional, Tuple from ...exceptions import QueryError -from .query import state_search_term_to_states +from .query import job_state_search_term_to_states -def parse_batch_jobs_query_v1(batch_id: int, q: str, last_job_id: Optional[int]): +def parse_list_batches_query_v1(user: str, q: str, last_batch_id: Optional[int]) -> Tuple[str, List[Any]]: + where_conditions = [ + '(billing_project_users.`user` = %s AND billing_project_users.billing_project = batches.billing_project)', + 'NOT deleted', + ] + where_args: List[Any] = [user] + + if last_batch_id is not None: + where_conditions.append('(batches.id < %s)') + where_args.append(last_batch_id) + + terms = q.split() + for _t in terms: + if _t[0] == '!': + negate = True + t = _t[1:] + else: + negate = False + t = _t + + if '=' in t: + k, v = t.split('=', 1) + condition = ''' +((batches.id) IN + (SELECT batch_id FROM batch_attributes + WHERE `key` = %s AND `value` = %s)) +''' + args = [k, v] + elif t.startswith('has:'): + k = t[4:] + condition = ''' +((batches.id) IN + (SELECT batch_id FROM batch_attributes + WHERE `key` = %s)) +''' + args = [k] + elif t.startswith('user:'): + k = t[5:] + condition = ''' +(batches.`user` = %s) +''' + args = [k] + elif t.startswith('billing_project:'): + k = t[16:] + condition = ''' +(billing_projects.name_cs = %s) +''' + args = [k] + elif t == 'open': + condition = "(`state` = 'open')" + args = [] + elif t == 'closed': + condition = "(`state` != 'open')" + args = [] + elif t == 'complete': + condition = "(`state` = 'complete')" + args = [] + elif t == 'running': + condition = "(`state` = 'running')" + args = [] + elif t == 'cancelled': + condition = '(batches_cancelled.id IS NOT NULL)' + args = [] + elif t == 'failure': + condition = '(n_failed > 0)' + args = [] + elif t == 'success': + # need complete because there might be no jobs + condition = "(`state` = 'complete' AND n_succeeded = n_jobs)" + args = [] + else: + raise QueryError(f'Invalid search term: {t}.') + + if negate: + condition = f'(NOT {condition})' + + where_conditions.append(condition) + where_args.extend(args) + + sql = f''' +WITH base_t AS ( + SELECT batches.*, + batches_cancelled.id IS NOT NULL AS cancelled, + batches_n_jobs_in_complete_states.n_completed, + batches_n_jobs_in_complete_states.n_succeeded, + batches_n_jobs_in_complete_states.n_failed, + batches_n_jobs_in_complete_states.n_cancelled + FROM batches + LEFT JOIN billing_projects ON batches.billing_project = billing_projects.name + LEFT JOIN batches_n_jobs_in_complete_states + ON batches.id = batches_n_jobs_in_complete_states.id + LEFT JOIN batches_cancelled + ON batches.id = batches_cancelled.id + STRAIGHT_JOIN billing_project_users ON batches.billing_project = billing_project_users.billing_project + WHERE {' AND '.join(where_conditions)} + ORDER BY id DESC + LIMIT 51 +) +SELECT base_t.*, COALESCE(SUM(`usage` * rate), 0) AS cost +FROM base_t +LEFT JOIN ( + SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` + FROM base_t + LEFT JOIN aggregated_batch_resources_v2 ON base_t.id = aggregated_batch_resources_v2.batch_id + GROUP BY batch_id, resource_id +) AS usage_t ON base_t.id = usage_t.batch_id +LEFT JOIN resources ON usage_t.resource_id = resources.resource_id +GROUP BY id +ORDER BY id DESC; +''' + + return (sql, where_args) + + +def parse_batch_jobs_query_v1(batch_id: int, q: str, last_job_id: Optional[int]) -> Tuple[str, List[Any]]: # batch has already been validated where_conditions = ['(jobs.batch_id = %s AND batch_updates.committed)'] where_args: List[Any] = [batch_id] @@ -44,8 +158,8 @@ def parse_batch_jobs_query_v1(batch_id: int, q: str, last_job_id: Optional[int]) WHERE `key` = %s)) ''' args = [k] - elif t in state_search_term_to_states: - values = state_search_term_to_states[t] + elif t in job_state_search_term_to_states: + values = job_state_search_term_to_states[t] condition = ' OR '.join(['(jobs.state = %s)' for _ in values]) condition = f'({condition})' args = [v.value for v in values] @@ -84,6 +198,5 @@ def parse_batch_jobs_query_v1(batch_id: int, q: str, last_job_id: Optional[int]) LEFT JOIN resources ON usage_t.resource_id = resources.resource_id GROUP BY base_t.batch_id, base_t.job_id; ''' - sql_args = where_args - return (sql, sql_args) + return (sql, where_args) diff --git a/batch/batch/front_end/query/query_v2.py b/batch/batch/front_end/query/query_v2.py index 297eac4b028..275c6daefe3 100644 --- a/batch/batch/front_end/query/query_v2.py +++ b/batch/batch/front_end/query/query_v2.py @@ -1,4 +1,4 @@ -from typing import List, Optional +from typing import Any, List, Optional, Tuple from ...exceptions import QueryError from .operators import ( @@ -9,20 +9,155 @@ pad_maybe_operator, ) from .query import ( - CostQuery, - DurationQuery, - EndTimeQuery, - InstanceCollectionQuery, - InstanceQuery, + BatchBillingProjectQuery, + BatchCostQuery, + BatchDurationQuery, + BatchEndTimeQuery, + BatchIdQuery, + BatchKeywordQuery, + BatchQuotedExactMatchQuery, + BatchStartTimeQuery, + BatchStateQuery, + BatchUnquotedPartialMatchQuery, + BatchUserQuery, + JobCostQuery, + JobDurationQuery, + JobEndTimeQuery, JobIdQuery, - KeywordQuery, + JobInstanceCollectionQuery, + JobInstanceQuery, + JobKeywordQuery, + JobQuotedExactMatchQuery, + JobStartTimeQuery, + JobStateQuery, + JobUnquotedPartialMatchQuery, Query, - QuotedExactMatchQuery, - StartTimeQuery, - StateQuery, - UnquotedPartialMatchQuery, ) +# ::= "" | "\n" +# ::= | | | | +# | | | | +# | +# ::= "=" | "==" | "!=" +# ::= "!~" | "=~" +# ::= | +# ::= ">=" | "<=" | ">" | "<" | +# ::= "batch_id" +# ::= "state" +# ::= "start_time" +# ::= "end_time" +# ::= "duration" +# ::= "cost" +# ::= "billing_project" +# ::= "user" +# ::= \" \" +# ::= + + +def parse_list_batches_query_v2(user: str, q: str, last_batch_id: Optional[int]) -> Tuple[str, List[Any]]: + queries: List[Query] = [] + + # logic to make time interval queries fast + min_start_gt_query: Optional[BatchStartTimeQuery] = None + max_end_lt_query: Optional[BatchEndTimeQuery] = None + + if q: + terms = q.rstrip().lstrip().split('\n') + for _term in terms: + _term = pad_maybe_operator(_term) + statement = _term.split() + if len(statement) == 1: + word = statement[0] + if word[0] == '"': + queries.append(BatchQuotedExactMatchQuery.parse(word)) + else: + queries.append(BatchUnquotedPartialMatchQuery.parse(word)) + elif len(statement) == 3: + left, op, right = statement + if left == 'batch_id': + queries.append(BatchIdQuery.parse(op, right)) + elif left == 'billing_project': + queries.append(BatchBillingProjectQuery.parse(op, right)) + elif left == 'user': + queries.append(BatchUserQuery.parse(op, right)) + elif left == 'state': + queries.append(BatchStateQuery.parse(op, right)) + elif left == 'start_time': + st_query = BatchStartTimeQuery.parse(op, right) + queries.append(st_query) + if (type(st_query.operator) in [GreaterThanOperator, GreaterThanEqualOperator]) and ( + min_start_gt_query is None or min_start_gt_query.time_msecs >= st_query.time_msecs + ): + min_start_gt_query = st_query + elif left == 'end_time': + et_query = BatchEndTimeQuery.parse(op, right) + queries.append(et_query) + if (type(et_query.operator) in [LessThanOperator, LessThanEqualOperator]) and ( + max_end_lt_query is None or max_end_lt_query.time_msecs <= et_query.time_msecs + ): + max_end_lt_query = et_query + elif left == 'duration': + queries.append(BatchDurationQuery.parse(op, right)) + elif left == 'cost': + queries.append(BatchCostQuery.parse(op, right)) + else: + queries.append(BatchKeywordQuery.parse(op, left, right)) + else: + raise QueryError(f'could not parse term "{_term}"') + + # this is to make time interval queries fast by using the bounds on both indices + if min_start_gt_query and max_end_lt_query and min_start_gt_query.time_msecs <= max_end_lt_query.time_msecs: + queries.append(BatchStartTimeQuery(max_end_lt_query.operator, max_end_lt_query.time_msecs)) + queries.append(BatchEndTimeQuery(min_start_gt_query.operator, min_start_gt_query.time_msecs)) + + # batch has already been validated + where_conditions = [ + '(billing_project_users.`user` = %s)', + 'NOT deleted', + ] + where_args: List[Any] = [user] + + if last_batch_id is not None: + where_conditions.append('(batches.id < %s)') + where_args.append(last_batch_id) + + for query in queries: + cond, args = query.query() + where_conditions.append(f'({cond})') + where_args += args + + sql = f''' +SELECT batches.*, + batches_cancelled.id IS NOT NULL AS cancelled, + batches_n_jobs_in_complete_states.n_completed, + batches_n_jobs_in_complete_states.n_succeeded, + batches_n_jobs_in_complete_states.n_failed, + batches_n_jobs_in_complete_states.n_cancelled, + cost_t.cost +FROM batches +LEFT JOIN billing_projects ON batches.billing_project = billing_projects.name +LEFT JOIN batches_n_jobs_in_complete_states ON batches.id = batches_n_jobs_in_complete_states.id +LEFT JOIN batches_cancelled ON batches.id = batches_cancelled.id +STRAIGHT_JOIN billing_project_users ON batches.billing_project = billing_project_users.billing_project +LEFT JOIN LATERAL ( + SELECT COALESCE(SUM(`usage` * rate), 0) AS cost + FROM ( + SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` + FROM aggregated_batch_resources_v2 + WHERE batches.id = aggregated_batch_resources_v2.batch_id + GROUP BY batch_id, resource_id + ) AS usage_t + LEFT JOIN resources ON usage_t.resource_id = resources.resource_id + GROUP BY batch_id +) AS cost_t ON TRUE +WHERE {' AND '.join(where_conditions)} +ORDER BY id DESC +LIMIT 51; +''' + + return (sql, where_args) + + # ::= "" | "\n" # ::= | | | | # | | | | @@ -43,12 +178,12 @@ # ::= -def parse_batch_jobs_query_v2(batch_id: int, q: str, last_job_id: Optional[int]): +def parse_batch_jobs_query_v2(batch_id: int, q: str, last_job_id: Optional[int]) -> Tuple[str, List[Any]]: queries: List[Query] = [] # logic to make time interval queries fast - min_start_gt_query: Optional[StartTimeQuery] = None - max_end_lt_query: Optional[EndTimeQuery] = None + min_start_gt_query: Optional[JobStartTimeQuery] = None + max_end_lt_query: Optional[JobEndTimeQuery] = None if q: terms = q.rstrip().lstrip().split('\n') @@ -58,46 +193,46 @@ def parse_batch_jobs_query_v2(batch_id: int, q: str, last_job_id: Optional[int]) if len(statement) == 1: word = statement[0] if word[0] == '"': - queries.append(QuotedExactMatchQuery.parse(word)) + queries.append(JobQuotedExactMatchQuery.parse(word)) else: - queries.append(UnquotedPartialMatchQuery.parse(word)) + queries.append(JobUnquotedPartialMatchQuery.parse(word)) elif len(statement) == 3: left, op, right = statement if left == 'instance': - queries.append(InstanceQuery.parse(op, right)) + queries.append(JobInstanceQuery.parse(op, right)) elif left == 'instance_collection': - queries.append(InstanceCollectionQuery.parse(op, right)) + queries.append(JobInstanceCollectionQuery.parse(op, right)) elif left == 'job_id': queries.append(JobIdQuery.parse(op, right)) elif left == 'state': - queries.append(StateQuery.parse(op, right)) + queries.append(JobStateQuery.parse(op, right)) elif left == 'start_time': - st_query = StartTimeQuery.parse(op, right) + st_query = JobStartTimeQuery.parse(op, right) queries.append(st_query) if (type(st_query.operator) in [GreaterThanOperator, GreaterThanEqualOperator]) and ( min_start_gt_query is None or min_start_gt_query.time_msecs >= st_query.time_msecs ): min_start_gt_query = st_query elif left == 'end_time': - et_query = EndTimeQuery.parse(op, right) + et_query = JobEndTimeQuery.parse(op, right) queries.append(et_query) if (type(et_query.operator) in [LessThanOperator, LessThanEqualOperator]) and ( max_end_lt_query is None or max_end_lt_query.time_msecs <= et_query.time_msecs ): max_end_lt_query = et_query elif left == 'duration': - queries.append(DurationQuery.parse(op, right)) + queries.append(JobDurationQuery.parse(op, right)) elif left == 'cost': - queries.append(CostQuery.parse(op, right)) + queries.append(JobCostQuery.parse(op, right)) else: - queries.append(KeywordQuery.parse(op, left, right)) + queries.append(JobKeywordQuery.parse(op, left, right)) else: raise QueryError(f'could not parse term "{_term}"') # this is to make time interval queries fast by using the bounds on both indices if min_start_gt_query and max_end_lt_query and min_start_gt_query.time_msecs <= max_end_lt_query.time_msecs: - queries.append(StartTimeQuery(max_end_lt_query.operator, max_end_lt_query.time_msecs)) - queries.append(EndTimeQuery(min_start_gt_query.operator, min_start_gt_query.time_msecs)) + queries.append(JobStartTimeQuery(max_end_lt_query.operator, max_end_lt_query.time_msecs)) + queries.append(JobEndTimeQuery(min_start_gt_query.operator, min_start_gt_query.time_msecs)) # batch has already been validated where_conditions = ['(jobs.batch_id = %s AND batch_updates.committed)'] @@ -113,12 +248,12 @@ def parse_batch_jobs_query_v2(batch_id: int, q: str, last_job_id: Optional[int]) if isinstance( query, ( - StartTimeQuery, - EndTimeQuery, - DurationQuery, - InstanceQuery, - QuotedExactMatchQuery, - UnquotedPartialMatchQuery, + JobStartTimeQuery, + JobEndTimeQuery, + JobDurationQuery, + JobInstanceQuery, + JobQuotedExactMatchQuery, + JobUnquotedPartialMatchQuery, ), ): uses_attempts_table = True @@ -157,6 +292,4 @@ def parse_batch_jobs_query_v2(batch_id: int, q: str, last_job_id: Optional[int]) LIMIT 50; ''' - sql_args = where_args - - return (sql, sql_args) + return (sql, where_args) diff --git a/batch/sql/add-list-batches-index.sql b/batch/sql/add-list-batches-index.sql new file mode 100644 index 00000000000..01b5f2b1040 --- /dev/null +++ b/batch/sql/add-list-batches-index.sql @@ -0,0 +1 @@ +CREATE INDEX batch_attributes_value ON `batch_attributes` (`value`(256)); diff --git a/batch/sql/estimated-current.sql b/batch/sql/estimated-current.sql index 6172b147b60..5bdf4d430c8 100644 --- a/batch/sql/estimated-current.sql +++ b/batch/sql/estimated-current.sql @@ -352,6 +352,7 @@ CREATE TABLE IF NOT EXISTS `batch_attributes` ( FOREIGN KEY (`batch_id`) REFERENCES batches(id) ON DELETE CASCADE ) ENGINE = InnoDB; CREATE INDEX batch_attributes_key_value ON `batch_attributes` (`key`, `value`(256)); +CREATE INDEX batch_attributes_value ON `batch_attributes` (`value`(256)); DROP TABLE IF EXISTS `aggregated_billing_project_user_resources_v2`; CREATE TABLE IF NOT EXISTS `aggregated_billing_project_user_resources_v2` ( diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index ca47ae4dbdc..c32362ee76a 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -270,7 +270,7 @@ def test_unsubmitted_state(client: BatchClient): j.wait() -def test_list_batches(client: BatchClient): +def test_list_batches_v1(client: BatchClient): tag = secrets.token_urlsafe(64) bb1 = create_batch(client, attributes={'tag': tag, 'name': 'b1'}) bb1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) @@ -317,6 +317,217 @@ def assert_batch_ids(expected: Set[int], q=None): assert_batch_ids({b2.id}, f'tag={tag} name=b2') +def test_list_batches_v2(client: BatchClient): + tag = secrets.token_urlsafe(64) + bb1 = create_batch(client, attributes={'tag': tag, 'name': 'b1'}) + bb1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) + b1 = bb1.submit() + + bb2 = create_batch(client, attributes={'tag': tag, 'name': 'b2'}) + bb2.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) + b2 = bb2.submit() + + batch_id_test_universe = {b1.id, b2.id} + + def assert_batch_ids(expected: Set[int], q=None): + assert expected.issubset(batch_id_test_universe) + max_id = max(batch_id_test_universe) + min_id = min(batch_id_test_universe) + span = max_id - min_id + 1 + # list_batches returns all batches for all prev run tests so we set a limit + batches = client.list_batches(q, last_batch_id=max_id + 1, limit=span, version=2) + full_actual = {b.id for b in batches} + actual = full_actual.intersection(batch_id_test_universe) + assert actual == expected, str((full_actual, max_id, span, b1.debug_info(), b2.debug_info())) + + try: + assert_batch_ids({b1.id, b2.id}) + + assert_batch_ids({b1.id, b2.id}, f'tag={tag}') + assert_batch_ids({b1.id, b2.id}, f'tag=~{tag}') + assert_batch_ids( + {b1.id, b2.id}, + f''' +name=~b +tag={tag} +''', + ) + assert_batch_ids( + {b1.id}, + f''' +name!~b2 +tag={tag} +''', + ) + assert_batch_ids( + {b1.id}, + f''' +name!=b2 +tag={tag} +''', + ) + assert_batch_ids( + {b2.id}, + f''' +b2 +tag={tag} +''', + ) + + b2.wait() + + assert_batch_ids( + {b1.id}, + f''' +state != complete +tag = {tag} +''', + ) + assert_batch_ids( + {b2.id}, + f''' +state=complete +tag={tag} +''', + ) + + assert_batch_ids( + {b1.id}, + f''' +state != success +tag={tag} +''', + ) + assert_batch_ids( + {b2.id}, + f''' +state == success +tag={tag} +''', + ) + + b1.cancel() + b1.wait() + + assert_batch_ids( + {b1.id}, + f''' +state!=success +tag={tag} +''', + ) + assert_batch_ids( + {b2.id}, + f''' +state = success +tag={tag} +''', + ) + + assert_batch_ids( + set(), + f''' +state != complete +tag={tag} +''', + ) + assert_batch_ids( + {b1.id, b2.id}, + f''' +state = complete +tag={tag} +''', + ) + + assert_batch_ids( + {b2.id}, + f''' +tag={tag} +name=b2 +''', + ) + + assert_batch_ids( + {b2.id}, + f''' +tag={tag} +"b2" +''', + ) + + assert_batch_ids( + {b2.id}, + f''' +tag=~{tag} +"b2" +''', + ) + + assert_batch_ids( + batch_id_test_universe, + f''' +user != foo +tag={tag} +''', + ) + + assert_batch_ids( + batch_id_test_universe, + f''' +billing_project = {client.billing_project} +tag={tag} +''', + ) + + assert_batch_ids( + {b1.id, b2.id}, + ''' +start_time >= 2023-02-24T17:15:25Z +end_time < 3000-02-24T17:15:25Z +''', + ) + + assert_batch_ids( + set(), + ''' +start_time >= 2023-02-24T17:15:25Z +end_time == 2023-02-24T17:15:25Z +''', + ) + + assert_batch_ids(set(), 'duration > 50000') + assert_batch_ids(set(), 'cost > 1000') + assert_batch_ids({b1.id}, f'batch_id = {b1.id}') + assert_batch_ids({b1.id}, f'batch_id == {b1.id}') + + with pytest.raises(httpx.ClientResponseError, match='could not parse term'): + assert_batch_ids(batch_id_test_universe, 'batch_id >= 1 abcde') + with pytest.raises(httpx.ClientResponseError, match='expected float, but found'): + assert_batch_ids(batch_id_test_universe, 'duration >= abcd') + with pytest.raises(httpx.ClientResponseError, match='expected int, but found'): + assert_batch_ids(batch_id_test_universe, 'batch_id >= abcd') + with pytest.raises(httpx.ClientResponseError, match='expected float, but found'): + assert_batch_ids(batch_id_test_universe, 'cost >= abcd') + with pytest.raises(httpx.ClientResponseError, match='unexpected operator'): + assert_batch_ids(batch_id_test_universe, 'state >= 1') + with pytest.raises(httpx.ClientResponseError, match='unknown state'): + assert_batch_ids(batch_id_test_universe, 'state = 1') + with pytest.raises(httpx.ClientResponseError, match='unexpected operator'): + assert_batch_ids(batch_id_test_universe, 'user >= 1') + with pytest.raises(httpx.ClientResponseError, match='unexpected operator'): + assert_batch_ids(batch_id_test_universe, 'billing_project >= 1') + with pytest.raises(httpx.ClientResponseError, match='expected date, but found'): + assert_batch_ids(batch_id_test_universe, 'start_time >= 1') + with pytest.raises(httpx.ClientResponseError, match='expected date, but found'): + assert_batch_ids(batch_id_test_universe, 'end_time >= 1') + + finally: + try: + b1.cancel() + finally: + b2.cancel() + + def test_list_jobs_v1(client: BatchClient): bb = create_batch(client) j_success = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) @@ -429,8 +640,26 @@ def assert_job_ids(expected, q=None): ''', ) + with pytest.raises(httpx.ClientResponseError, match='could not parse term'): + assert_job_ids(no_jobs, 'job_id >= 1 abcde') with pytest.raises(httpx.ClientResponseError, match='expected float, but found'): assert_job_ids(no_jobs, 'duration >= abcd') + with pytest.raises(httpx.ClientResponseError, match='expected int, but found'): + assert_job_ids(no_jobs, 'job_id >= abcd') + with pytest.raises(httpx.ClientResponseError, match='expected float, but found'): + assert_job_ids(no_jobs, 'cost >= abcd') + with pytest.raises(httpx.ClientResponseError, match='unexpected operator'): + assert_job_ids(no_jobs, 'state >= 1') + with pytest.raises(httpx.ClientResponseError, match='unknown state'): + assert_job_ids(no_jobs, 'state = 1') + with pytest.raises(httpx.ClientResponseError, match='unexpected operator'): + assert_job_ids(no_jobs, 'instance_collection >= 1') + with pytest.raises(httpx.ClientResponseError, match='unexpected operator'): + assert_job_ids(no_jobs, 'instance >= 1') + with pytest.raises(httpx.ClientResponseError, match='expected date, but found'): + assert_job_ids(no_jobs, 'start_time >= 1') + with pytest.raises(httpx.ClientResponseError, match='expected date, but found'): + assert_job_ids(no_jobs, 'end_time >= 1') finally: b.cancel() diff --git a/build.yaml b/build.yaml index c0130d9ae73..0af6d2f4b0d 100644 --- a/build.yaml +++ b/build.yaml @@ -2279,6 +2279,9 @@ steps: - name: add-jobs-ready-time script: /io/sql/add-jobs-ready-time.sql online: true + - name: add-list-batches-index + script: /io/sql/add-list-batches-index.sql + online: true inputs: - from: /repo/batch/sql to: /io/sql diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index d78c23da538..4305868c701 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -370,7 +370,8 @@ async def cancel(self): await self._client._patch(f'/api/v1alpha/batches/{self.id}/cancel') async def jobs(self, q: Optional[str] = None, version: Optional[int] = None): - version = version or 1 + if version is None: + version = 1 last_job_id = None while True: params = {} @@ -890,7 +891,9 @@ async def _delete(self, path) -> aiohttp.ClientResponse: def reset_billing_project(self, billing_project): self.billing_project = billing_project - async def list_batches(self, q=None, last_batch_id=None, limit=2 ** 64): + async def list_batches(self, q=None, last_batch_id=None, limit=2 ** 64, version=None): + if version is None: + version = 1 n = 0 while True: params = {} @@ -899,7 +902,7 @@ async def list_batches(self, q=None, last_batch_id=None, limit=2 ** 64): if last_batch_id is not None: params['last_batch_id'] = last_batch_id - resp = await self._get('/api/v1alpha/batches', params=params) + resp = await self._get(f'/api/v{version}alpha/batches', params=params) body = await resp.json() for batch in body['batches']: diff --git a/hail/python/hailtop/batch_client/client.py b/hail/python/hailtop/batch_client/client.py index f03ab381952..2b4d6a9ba73 100644 --- a/hail/python/hailtop/batch_client/client.py +++ b/hail/python/hailtop/batch_client/client.py @@ -301,8 +301,8 @@ def billing_project(self): def reset_billing_project(self, billing_project): self._async_client.reset_billing_project(billing_project) - def list_batches(self, q=None, last_batch_id=None, limit=2**64): - for b in agen_to_blocking(self._async_client.list_batches(q=q, last_batch_id=last_batch_id, limit=limit)): + def list_batches(self, q=None, last_batch_id=None, limit=2**64, version=None): + for b in agen_to_blocking(self._async_client.list_batches(q=q, last_batch_id=last_batch_id, limit=limit, version=version)): yield Batch.from_async_batch(b) def get_job(self, batch_id, job_id): From de11fba2fe9a46ea13328d794a9eb97d34405df6 Mon Sep 17 00:00:00 2001 From: jigold Date: Wed, 12 Jul 2023 13:10:27 -0400 Subject: [PATCH 013/180] [batch] Fix list batches query and test (#13237) The test that lists batches timed out. The main problem is the limit in the aioclient used by the test_batch tests was passing a string rather than an integer. I assumed downstream the function was passing an integer. Therefore, we were doing this: batch_id < "137" and not batch_id < 137. So the query was running forever and scanning all batches from the test user. I also was missing a tag annotation on the queries, but that was not causing the timeout. --- batch/batch/front_end/front_end.py | 65 +++++++++++++++++------------- batch/test/test_batch.py | 38 ++++++++++++++--- 2 files changed, 70 insertions(+), 33 deletions(-) diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index dc943128b44..91f05e36f40 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -11,7 +11,7 @@ import traceback from functools import wraps from numbers import Number -from typing import Dict, Optional, Tuple, Union +from typing import Awaitable, Callable, Dict, Optional, Tuple, TypeVar, Union import aiohttp import aiohttp_session @@ -25,6 +25,7 @@ from aiohttp import web from plotly.subplots import make_subplots from prometheus_async.aio.web import server_stats # type: ignore +from typing_extensions import ParamSpec from gear import ( AuthClient, @@ -113,6 +114,10 @@ BATCH_JOB_DEFAULT_PREEMPTIBLE = True +T = TypeVar('T') +P = ParamSpec('P') + + def rest_authenticated_developers_or_auth_only(fun): @auth.rest_authenticated_users_only @wraps(fun) @@ -189,6 +194,12 @@ async def wrapped(request, userdata, *args, **kwargs): return wrap +def cast_query_param_to_int(param: Optional[str]) -> Optional[int]: + if param is not None: + return int(param) + return None + + @routes.get('/healthcheck') async def get_healthcheck(request): # pylint: disable=W0613 return web.Response() @@ -210,7 +221,9 @@ async def rest_get_supported_regions(request, userdata): # pylint: disable=unus return json_response(list(request.app['regions'].keys())) -async def _handle_ui_error(session, f, *args, **kwargs): +async def _handle_ui_error( + session: aiohttp_session.Session, f: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs +) -> T: try: return await f(*args, **kwargs) except KeyError as e: @@ -227,17 +240,17 @@ async def _handle_ui_error(session, f, *args, **kwargs): raise -async def _handle_api_error(f, *args, **kwargs): +async def _handle_api_error(f: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs) -> Optional[T]: try: return await f(*args, **kwargs) except BatchOperationAlreadyCompletedError as e: log.info(e.message) - return + return None except BatchUserError as e: raise e.http_response() -async def _query_batch_jobs(request, batch_id: int, version: int, q: str, last_job_id: Optional[int]): +async def _query_batch_jobs(request: web.Request, batch_id: int, version: int, q: str, last_job_id: Optional[int]): db: Database = request.app['db'] if version == 1: sql, sql_args = parse_batch_jobs_query_v1(batch_id, q, last_job_id) @@ -279,24 +292,22 @@ async def _get_jobs(request, batch_id: int, version: int, q: str, last_job_id: O @routes.get('/api/v1alpha/batches/{batch_id}/jobs') @rest_billing_project_users_only @add_metadata_to_request -async def get_jobs_v1(request, userdata, batch_id): # pylint: disable=unused-argument +async def get_jobs_v1(request: web.Request, userdata: dict, batch_id: int): # pylint: disable=unused-argument q = request.query.get('q', '') - last_job_id = request.query.get('last_job_id') - if last_job_id is not None: - last_job_id = int(last_job_id) + last_job_id = cast_query_param_to_int(request.query.get('last_job_id')) resp = await _handle_api_error(_get_jobs, request, batch_id, 1, q, last_job_id) + assert resp is not None return json_response(resp) @routes.get('/api/v2alpha/batches/{batch_id}/jobs') @rest_billing_project_users_only @add_metadata_to_request -async def get_jobs_v2(request, userdata, batch_id): # pylint: disable=unused-argument +async def get_jobs_v2(request: web.Request, userdata: dict, batch_id: int): # pylint: disable=unused-argument q = request.query.get('q', '') - last_job_id = request.query.get('last_job_id') - if last_job_id is not None: - last_job_id = int(last_job_id) + last_job_id = cast_query_param_to_int(request.query.get('last_job_id')) resp = await _handle_api_error(_get_jobs, request, batch_id, 2, q, last_job_id) + assert resp is not None return json_response(resp) @@ -634,8 +645,10 @@ async def _query_batches(request, user: str, q: str, version: int, last_batch_id async def get_batches_v1(request, userdata): # pylint: disable=unused-argument user = userdata['username'] q = request.query.get('q', f'user:{user}') - last_batch_id = request.query.get('last_batch_id') - batches, last_batch_id = await _handle_api_error(_query_batches, request, user, q, 1, last_batch_id) + last_batch_id = cast_query_param_to_int(request.query.get('last_batch_id')) + result = await _handle_api_error(_query_batches, request, user, q, 1, last_batch_id) + assert result is not None + batches, last_batch_id = result body = {'batches': batches} if last_batch_id is not None: body['last_batch_id'] = last_batch_id @@ -648,8 +661,10 @@ async def get_batches_v1(request, userdata): # pylint: disable=unused-argument async def get_batches_v2(request, userdata): # pylint: disable=unused-argument user = userdata['username'] q = request.query.get('q', f'user = {user}') - last_batch_id = request.query.get('last_batch_id') - batches, last_batch_id = await _handle_api_error(_query_batches, request, user, q, 2, last_batch_id) + last_batch_id = cast_query_param_to_int(request.query.get('last_batch_id')) + result = await _handle_api_error(_query_batches, request, user, q, 2, last_batch_id) + assert result is not None + batches, last_batch_id = result body = {'batches': batches} if last_batch_id is not None: body['last_batch_id'] = last_batch_id @@ -1631,9 +1646,7 @@ async def ui_batch(request, userdata, batch_id): batch = await _get_batch(app, batch_id) q = request.query.get('q', '') - last_job_id = request.query.get('last_job_id') - if last_job_id is not None: - last_job_id = int(last_job_id) + last_job_id = cast_query_param_to_int(request.query.get('last_job_id')) try: jobs, last_job_id = await _query_batch_jobs(request, batch_id, CURRENT_QUERY_VERSION, q, last_job_id) @@ -1697,17 +1710,15 @@ async def ui_delete_batch(request, userdata, batch_id): # pylint: disable=unuse @routes.get('/batches', name='batches') @auth.web_authenticated_users_only() @catch_ui_error_in_dev -async def ui_batches(request, userdata): +async def ui_batches(request: web.Request, userdata: dict): session = await aiohttp_session.get_session(request) user = userdata['username'] q = request.query.get('q', f'user:{user}') - last_batch_id = request.query.get('last_batch_id') - if last_batch_id is not None: - last_batch_id = int(last_batch_id) + last_batch_id = cast_query_param_to_int(request.query.get('last_batch_id')) try: - batches, last_batch_id = await _handle_ui_error( - session, _query_batches, request, user, q, CURRENT_QUERY_VERSION, last_batch_id - ) + result = await _handle_ui_error(session, _query_batches, request, user, q, CURRENT_QUERY_VERSION, last_batch_id) + assert result is not None + batches, last_batch_id = result except asyncio.CancelledError: raise except Exception: diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index c32362ee76a..54fe6e97ad9 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -481,24 +481,50 @@ def assert_batch_ids(expected: Set[int], q=None): assert_batch_ids( {b1.id, b2.id}, - ''' + f''' start_time >= 2023-02-24T17:15:25Z end_time < 3000-02-24T17:15:25Z +tag = {tag} ''', ) assert_batch_ids( set(), - ''' + f''' start_time >= 2023-02-24T17:15:25Z end_time == 2023-02-24T17:15:25Z +tag = {tag} ''', ) - assert_batch_ids(set(), 'duration > 50000') - assert_batch_ids(set(), 'cost > 1000') - assert_batch_ids({b1.id}, f'batch_id = {b1.id}') - assert_batch_ids({b1.id}, f'batch_id == {b1.id}') + assert_batch_ids( + set(), + f''' +duration > 50000 +tag = {tag} +''', + ) + assert_batch_ids( + set(), + f''' +cost > 1000 +tag = {tag} +''', + ) + assert_batch_ids( + {b1.id}, + f''' +batch_id = {b1.id} +tag = {tag} +''', + ) + assert_batch_ids( + {b1.id}, + f''' +batch_id == {b1.id} +tag = {tag} +''', + ) with pytest.raises(httpx.ClientResponseError, match='could not parse term'): assert_batch_ids(batch_id_test_universe, 'batch_id >= 1 abcde') From 068c0f2731798185fe2e36adc9d30040ad7afb26 Mon Sep 17 00:00:00 2001 From: jigold Date: Fri, 14 Jul 2023 13:53:55 -0400 Subject: [PATCH 014/180] [batch] Fix schedulable cores in UI on pools page (#13236) --- batch/batch/driver/instance_collection/base.py | 7 +++++++ batch/batch/driver/templates/index.html | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/batch/batch/driver/instance_collection/base.py b/batch/batch/driver/instance_collection/base.py index f49530258c3..435117c8072 100644 --- a/batch/batch/driver/instance_collection/base.py +++ b/batch/batch/driver/instance_collection/base.py @@ -137,6 +137,7 @@ def __init__(self): # pending and active self.live_free_cores_mcpu = 0 self.live_total_cores_mcpu = 0 + self.live_schedulable_free_cores_mcpu = 0 def remove_instance(self, instance: Instance): self.n_instances_by_state[instance.state] -= 1 @@ -146,6 +147,9 @@ def remove_instance(self, instance: Instance): self.live_total_cores_mcpu -= instance.cores_mcpu self.live_free_cores_mcpu_by_region[instance.region] -= instance.free_cores_mcpu_nonnegative + if instance.state == 'active': + self.live_schedulable_free_cores_mcpu -= instance.free_cores_mcpu_nonnegative + def add_instance(self, instance: Instance): self.n_instances_by_state[instance.state] += 1 @@ -154,6 +158,9 @@ def add_instance(self, instance: Instance): self.live_total_cores_mcpu += instance.cores_mcpu self.live_free_cores_mcpu_by_region[instance.region] += instance.free_cores_mcpu_nonnegative + if instance.state == 'active': + self.live_schedulable_free_cores_mcpu += instance.free_cores_mcpu_nonnegative + class InstanceCollection: def __init__( diff --git a/batch/batch/driver/templates/index.html b/batch/batch/driver/templates/index.html index d6779c716e7..161f0292bc2 100644 --- a/batch/batch/driver/templates/index.html +++ b/batch/batch/driver/templates/index.html @@ -53,7 +53,7 @@

Pools

{{ pool.all_versions_instances_by_state['inactive'] }} {{ pool.all_versions_instances_by_state['deleted'] }} {{ pool.all_versions_provisioned_cores_mcpu / 1000 }} - {{ pool.current_worker_version_stats.live_free_cores_mcpu / 1000 }} / {{ pool.all_versions_provisioned_cores_mcpu / 1000 }} + {{ pool.current_worker_version_stats.live_schedulable_free_cores_mcpu / 1000 }} / {{ pool.all_versions_provisioned_cores_mcpu / 1000 }} {% endfor %} From da86326fa70e47dc0d42e3d61236b2f1b7faa9c8 Mon Sep 17 00:00:00 2001 From: Iris Rademacher <84595986+iris-garden@users.noreply.github.com> Date: Fri, 14 Jul 2023 15:09:22 -0400 Subject: [PATCH 015/180] [ci/ui] filters jobs by status (#13148) Currently, when the user views the jobs for a CI pipeline, either on the `pr.html` page or the `batch.html` page, they are displayed all together in a big table, like so: Screenshot 2023-06-06 at 15 30 21 This change filters the jobs out into smaller tables, with any failed jobs displayed first, followed by any jobs that are currently running, then any pending jobs, then the rest. Example with failed job: Screenshot 2023-06-06 at 15 12 36 Example with running/pending jobs: Screenshot 2023-06-06 at 15 10 54 --- ci/ci/ci.py | 12 ++++++++++-- ci/ci/templates/batch.html | 4 ++-- ci/ci/templates/filtered-jobs.html | 17 +++++++++++++++++ ci/ci/templates/pr.html | 4 ++-- 4 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 ci/ci/templates/filtered-jobs.html diff --git a/ci/ci/ci.py b/ci/ci/ci.py index a8fd881c97c..ec344ec7efb 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -151,6 +151,13 @@ def wb_and_pr_from_request(request): return wb, wb.prs[pr_number] +def filter_jobs(jobs): + filtered: Dict[str, list] = {"running": [], "failed": [], "pending": [], "jobs": []} + for job in jobs: + filtered.get(job["state"].lower(), filtered["jobs"]).append(job) + return {"completed" if k == "jobs" else k: v if len(v) > 0 else None for k, v in filtered.items()} + + @routes.get('/watched_branches/{watched_branch_index}/pr/{pr_number}') @auth.web_authenticated_developers_only() async def get_pr(request, userdata): # pylint: disable=unused-argument @@ -169,7 +176,7 @@ async def get_pr(request, userdata): # pylint: disable=unused-argument for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) page_context['batch'] = status - page_context['jobs'] = jobs + page_context.update(filter_jobs(jobs)) artifacts_uri = f'{STORAGE_URI}/build/{batch.attributes["token"]}' page_context['artifacts_uri'] = artifacts_uri page_context['artifacts_url'] = storage_uri_to_url(artifacts_uri) @@ -244,7 +251,8 @@ async def get_batch(request, userdata): for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) wb = get_maybe_wb_for_batch(b) - page_context = {'batch': status, 'jobs': jobs, 'wb': wb} + page_context = {'batch': status, 'wb': wb} + page_context.update(filter_jobs(jobs)) return await render_template('ci', request, userdata, 'batch.html', page_context) diff --git a/ci/ci/templates/batch.html b/ci/ci/templates/batch.html index 03a8a0b06cc..aa305c33822 100644 --- a/ci/ci/templates/batch.html +++ b/ci/ci/templates/batch.html @@ -1,4 +1,4 @@ -{% from "job-table.html" import job_table with context %} +{% from "filtered-jobs.html" import filtered_jobs with context %} {% extends "layout.html" %} {% block title %}Batch {{ batch['id'] }}{% endblock %} {% block head %} @@ -29,7 +29,7 @@

Attributes

{% endif %}

Jobs

- {{ job_table(jobs, "jobs", "jobsSearchBar") }} + {{ filtered_jobs(running, failed, pending, completed) }} diff --git a/ci/ci/templates/filtered-jobs.html b/ci/ci/templates/filtered-jobs.html new file mode 100644 index 00000000000..68600a7a52e --- /dev/null +++ b/ci/ci/templates/filtered-jobs.html @@ -0,0 +1,17 @@ +{% from "job-table.html" import job_table with context %} +{% macro filtered_jobs(running, failed, pending, completed) %} +{% if failed is not none %} +

Failed

+ {{ job_table(failed, "failed-jobs", "failedJobsSearchBar") }} +{% endif %} +{% if running is not none %} +

Running

+ {{ job_table(running, "running-jobs", "runningJobsSearchBar") }} +{% endif %} +{% if pending is not none %} +

Pending

+ {{ job_table(pending, "pending-jobs", "pendingJobsSearchBar") }} +{% endif %} +

Completed

+{{ job_table(completed, "completed-jobs", "completedJobsSearchBar") }} +{% endmacro %} diff --git a/ci/ci/templates/pr.html b/ci/ci/templates/pr.html index 5c67fb3db76..18b5cd10fa1 100644 --- a/ci/ci/templates/pr.html +++ b/ci/ci/templates/pr.html @@ -1,4 +1,4 @@ -{% from "job-table.html" import job_table with context %} +{% from "filtered-jobs.html" import filtered_jobs with context %} {% extends "layout.html" %} {% block title %}PR {{ number }}{% endblock %} {% block head %} @@ -25,7 +25,7 @@

{{ pr.title }} Retry

Jobs

- {{ job_table(jobs, "jobs", "jobsSearchBar") }} + {{ filtered_jobs(running, failed, pending, completed) }} {% elif exception is defined %}

Build error:


From 758116704da0835a1c02138310ddc4b3161ce26a Mon Sep 17 00:00:00 2001
From: Dan King 
Date: Mon, 17 Jul 2023 10:44:27 -0400
Subject: [PATCH 016/180] [query] skip combiner tests until combiner is fast in
 QoB (#13240)

---
 hail/python/test/hail/vds/test_combiner.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hail/python/test/hail/vds/test_combiner.py b/hail/python/test/hail/vds/test_combiner.py
index 1b4e4726ff2..a91c4a560c7 100644
--- a/hail/python/test/hail/vds/test_combiner.py
+++ b/hail/python/test/hail/vds/test_combiner.py
@@ -7,8 +7,7 @@
 from hail.utils.misc import new_temp_file
 from hail.vds.combiner import combine_variant_datasets, new_combiner, load_combiner, transform_gvcf
 from hail.vds.combiner.combine import defined_entry_fields
-from ..helpers import resource, fails_local_backend, fails_service_backend, test_timeout
-
+from ..helpers import resource, skip_when_service_backend, test_timeout
 
 all_samples = ['HG00308', 'HG00592', 'HG02230', 'NA18534', 'NA20760',
                'NA18530', 'HG03805', 'HG02223', 'HG00637', 'NA12249',
@@ -110,6 +109,7 @@ def test_move_load_combiner_plan():
 
 
 @test_timeout(10 * 60)
+@skip_when_service_backend(reason='Combiner makes extensive use of the Backend API which are serviced by starting a Hail Batch job to execute them. This test will be too slow until we change the combiner to use many fewer executes.')
 def test_combiner_run():
     tmpdir = new_temp_file()
     samples = all_samples[:5]

From 7db520f63ce100e9540521bffeecdf07a8660cca Mon Sep 17 00:00:00 2001
From: Dan King 
Date: Mon, 17 Jul 2023 11:45:55 -0400
Subject: [PATCH 017/180] [transient-error] new transient error from GCS
 (#13170)

https://ci.hail.is/batches/7525669/jobs/178
---
 .../main/scala/is/hail/services/package.scala | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/hail/src/main/scala/is/hail/services/package.scala b/hail/src/main/scala/is/hail/services/package.scala
index 2f0756a293f..88cdc95b62b 100644
--- a/hail/src/main/scala/is/hail/services/package.scala
+++ b/hail/src/main/scala/is/hail/services/package.scala
@@ -83,6 +83,28 @@ package object services {
       case e: HttpResponseException
           if RETRYABLE_HTTP_STATUS_CODES.contains(e.getStatusCode()) =>
         true
+      case e: HttpResponseException
+          if (e.getStatusCode() == 410 &&
+            e.getMessage != null &&
+            e.getMessage.contains("\"code\": 503,") &&
+            e.getMessage.contains("\"message\": \"Backend Error\",")
+          ) =>
+        // hail.utils.java.FatalError: HttpResponseException: 410 Gone
+        // PUT https://storage.googleapis.com/upload/storage/v1/b/hail-test-ezlis/o?name=tmp/hail/nBHPQsrxGvJ4T7Ybdp1IjQ/persist_TableObF6TwC6hv/rows/metadata.json.gz&uploadType=resumable&upload_id=ADPycdsFEtq65NC-ahk6tt6qdD3bKC3asqVSJELnirlpLG_ZDV_637Nn7NourXYTgMRKlX3bQVe9BfD_QfIP_kupTxVQyrJWQJrj
+        // {
+        //   "error": {
+        //     "code": 503,
+        //     "message": "Backend Error",
+        //     "errors": [
+        //       {
+        //         "message": "Backend Error",
+        //         "domain": "global",
+        //         "reason": "backendError"
+        //       }
+        //     ]
+        //   }
+        // }
+        true
       case e: ClientResponseException
           if RETRYABLE_HTTP_STATUS_CODES.contains(e.status) =>
         true

From 4d8f0901fb2534fc5dcf72c8c76829225ccaf034 Mon Sep 17 00:00:00 2001
From: Iris Rademacher <84595986+iris-garden@users.noreply.github.com>
Date: Tue, 18 Jul 2023 09:58:25 -0400
Subject: [PATCH 018/180] [tests] prevents collisions in batch advanced search
 partial match test (#13243)

---
 batch/test/test_batch.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py
index 54fe6e97ad9..798ea0776d6 100644
--- a/batch/test/test_batch.py
+++ b/batch/test/test_batch.py
@@ -318,7 +318,9 @@ def assert_batch_ids(expected: Set[int], q=None):
 
 
 def test_list_batches_v2(client: BatchClient):
-    tag = secrets.token_urlsafe(64)
+    # replace any occurrences of the substring "b2" in the tag to avoid collisions with the batch name for the partial
+    # match test
+    tag = secrets.token_urlsafe(64).replace("b2", "00")
     bb1 = create_batch(client, attributes={'tag': tag, 'name': 'b1'})
     bb1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600'])
     b1 = bb1.submit()

From 044d6bb4537be041aa3f1a2046c5a25f0405621b Mon Sep 17 00:00:00 2001
From: Dan King 
Date: Tue, 18 Jul 2023 15:34:24 -0400
Subject: [PATCH 019/180] [hailtop.fs] use parallelism to list directories
 (#13253)

Qin He reported that listing a folder containing around 50k files took
1h15. This new code takes ~16 seconds which is about how long it takes
`gcloud storage ls`.

There are two improvements:

1. Use `bounded_gather2`. The use of a semaphore in `bounded_gather2`,
which is missing from `bounded_gather`, allows it to be used
recursively. In particular, suppose we had a semaphore of
50. The outer `bounded_gather2` might need 20 slots to run its 20 paths
in parallel. That leaves 30 slots of parallelism left over for its
children. By passing the semaphore down, we let our children
optimistically use some of that excess parallelism.

2. If we happen to have the `StatResult` for a particular object, we
should never again look it up. In particular, getting the `StatResult`
for every file in a directory can be done in O(1) requests. Getting the
`StatResult` for each of those files individually (using their full
paths) is necessarily O(N). If there was at least one glob and also
there are no `suffix_components`, then we can use the `StatResult`s that
we learned when checking the glog pattern.

The latter point is perhaps a bit more clear with examples:

1. `gs://foo/bar/baz`. Since there are no globs, we can make exactly one
API request to list `gs://foo/bar/baz`.

2. `gs://foo/b*r/baz`. In this case, we must make one API request to
list `gs://foo/`. This gives us a list of paths under that prefix. We
check each path for conformance to the glob pattern `gs://foo/b*r`. For
any path that matches, we must then list `/baz` which
may itself be a directory containing files. Overall we make O(1) API
requests to do the glob and then O(K) API requests to get the final
`StatResult`s, where K is the number of paths matching the glob pattern.

3. `gs://foo/bar/b*z`. In this case, we must make one API request to
list `gs://foo/bar/`. In `main`, we then throw away the `StatResult`s we
got from that API request! Now we have to make O(K) requests to recover
those `StatResult`s for all K paths that match the glob pattern. This PR
just caches the `StatResult`s of the most recent globbing. If there is
no suffix to later append, then we can just re-use the `StatResult`s we
already have!


cc: @daniel-goldstein since you've reviewed this before. Might be of
interest.
---
 hail/python/hailtop/fs/router_fs.py | 57 ++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 14 deletions(-)

diff --git a/hail/python/hailtop/fs/router_fs.py b/hail/python/hailtop/fs/router_fs.py
index 9bca2294451..92e31f755d6 100644
--- a/hail/python/hailtop/fs/router_fs.py
+++ b/hail/python/hailtop/fs/router_fs.py
@@ -10,7 +10,7 @@
 from hailtop.aiotools.fs import Copier, Transfer, FileListEntry, ReadableStream, WritableStream
 from hailtop.aiotools.local_fs import LocalAsyncFS
 from hailtop.aiotools.router_fs import RouterAsyncFS
-from hailtop.utils import bounded_gather, async_to_blocking
+from hailtop.utils import bounded_gather2, async_to_blocking
 
 from .fs import FS
 from .stat_result import FileType, StatResult
@@ -280,11 +280,13 @@ async def _async_ls(self,
                         *,
                         error_when_file_and_directory: bool = True,
                         _max_simultaneous_files: int = 50) -> List[StatResult]:
+        sema = asyncio.Semaphore(_max_simultaneous_files)
+
         async def ls_no_glob(path) -> List[StatResult]:
             try:
                 return await self._ls_no_glob(path,
                                               error_when_file_and_directory=error_when_file_and_directory,
-                                              _max_simultaneous_files=_max_simultaneous_files)
+                                              sema=sema)
             except FileNotFoundError:
                 return []
 
@@ -317,22 +319,47 @@ async def ls_no_glob(path) -> List[StatResult]:
                 first_prefix = ['file:', '', '']
             else:
                 first_prefix = []
+
+        cached_stats_for_each_cumulative_prefix: Optional[List[StatResult]] = None
         cumulative_prefixes = [first_prefix]
 
         for intervening_components, single_component_glob_pattern in glob_components:
-            cumulative_prefixes = [
-                stat.path.split('/')
-                for cumulative_prefix in cumulative_prefixes
-                for stat in await ls_no_glob('/'.join([*cumulative_prefix, *intervening_components]))
+            stats_grouped_by_prefix = await bounded_gather2(
+                sema,
+                *[
+                    functools.partial(ls_no_glob, '/'.join([*cumulative_prefix, *intervening_components]))
+                    for cumulative_prefix in cumulative_prefixes
+                ],
+                cancel_on_error=True
+            )
+            cached_stats_for_each_cumulative_prefix = [
+                stat
+                for stats_for_one_prefix, cumulative_prefix in zip(stats_grouped_by_prefix, cumulative_prefixes)
+                for stat in stats_for_one_prefix
                 if fnmatch.fnmatch(stat.path,
                                    '/'.join([*cumulative_prefix, *intervening_components, single_component_glob_pattern]))
             ]
+            cumulative_prefixes = [
+                stat.path.split('/')
+                for stat in cached_stats_for_each_cumulative_prefix
+            ]
 
-        found_stats = [
-            stat
-            for cumulative_prefix in cumulative_prefixes
-            for stat in await ls_no_glob('/'.join([*cumulative_prefix, *suffix_components]))
-        ]
+        if len(suffix_components) == 0 and cached_stats_for_each_cumulative_prefix is not None:
+            found_stats = cached_stats_for_each_cumulative_prefix
+        else:
+            found_stats_grouped_by_prefix = await bounded_gather2(
+                sema,
+                *[
+                    functools.partial(ls_no_glob, '/'.join([*cumulative_prefix, *suffix_components]))
+                        for cumulative_prefix in cumulative_prefixes
+                ],
+                cancel_on_error=True
+            )
+            found_stats = [
+                stat
+                for stats in found_stats_grouped_by_prefix
+                for stat in stats
+            ]
 
         if len(glob_components) == 0 and len(found_stats) == 0:
             # Unless we are using a glob pattern, a path referring to no files should error
@@ -343,13 +370,15 @@ async def _ls_no_glob(self,
                           path: str,
                           *,
                           error_when_file_and_directory: bool = True,
-                          _max_simultaneous_files: int = 50) -> List[StatResult]:
+                          sema: asyncio.Semaphore) -> List[StatResult]:
         async def ls_as_dir() -> Optional[List[StatResult]]:
             try:
-                return await bounded_gather(
+                return await bounded_gather2(
+                    sema,
                     *[functools.partial(self._fle_to_dict, fle)
                       async for fle in await self.afs.listfiles(path)],
-                    parallelism=_max_simultaneous_files)
+                    cancel_on_error=True
+                )
             except (FileNotFoundError, NotADirectoryError):
                 return None
         maybe_sb_and_t, maybe_contents = await asyncio.gather(

From 138d69e126bca728678b8e9f2c94fc3aab301ef5 Mon Sep 17 00:00:00 2001
From: jigold 
Date: Tue, 18 Jul 2023 19:04:03 -0400
Subject: [PATCH 020/180] [ci] Add sjparsa as an authorized user (#13257)

---
 ci/ci/constants.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ci/ci/constants.py b/ci/ci/constants.py
index aca0df0d8fd..830806af193 100644
--- a/ci/ci/constants.py
+++ b/ci/ci/constants.py
@@ -33,4 +33,5 @@ def __init__(self, gh_username: str, hail_username: Optional[str] = None, teams:
     User('illusional', 'mfrankli', []),
     User('iris-garden', 'irademac'),
     User('ehigham', 'ehigham', [COMPILER_TEAM]),
+    User('sjparsa', 'parsa'),
 ]

From a599c55cdffe8dcaf06b81340d307250daff612b Mon Sep 17 00:00:00 2001
From: Dan King 
Date: Fri, 21 Jul 2023 13:29:14 -0400
Subject: [PATCH 021/180] [k8s] update to avoid unsupported apiVersions
 (#13277)

---
 auth/deployment.yaml                          |  6 ++++--
 batch/deployment.yaml                         |  6 ++++--
 bootstrap-gateway/deployment.yaml             |  6 ++++--
 build.yaml                                    | 21 ++++++++++++++++++-
 gateway/deployment.yaml                       |  6 ++++--
 hail/python/test/hail/methods/test_pca.py     | 10 ++++-----
 hail/python/test/hail/methods/test_statgen.py |  2 +-
 hail/python/test/hail/table/test_table.py     |  2 +-
 hail/python/test/hail/vds/test_vds.py         |  1 +
 notebook/deployment.yaml                      |  8 ++++---
 website/deployment.yaml                       |  6 ++++--
 11 files changed, 53 insertions(+), 21 deletions(-)

diff --git a/auth/deployment.yaml b/auth/deployment.yaml
index 102fceef97f..bcac1fea2ee 100644
--- a/auth/deployment.yaml
+++ b/auth/deployment.yaml
@@ -251,7 +251,7 @@ spec:
            secretName: ssl-config-auth
 {% if deploy %}
 ---
-apiVersion: autoscaling/v2beta1
+apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   name: auth
@@ -266,7 +266,9 @@ spec:
    - type: Resource
      resource:
        name: cpu
-       targetAverageUtilization: 2500
+       target:
+         type: Utilization
+         averageUtilization: 2500
 ---
 apiVersion: policy/v1
 kind: PodDisruptionBudget
diff --git a/batch/deployment.yaml b/batch/deployment.yaml
index 89190e83bb5..558e06b8c19 100644
--- a/batch/deployment.yaml
+++ b/batch/deployment.yaml
@@ -491,7 +491,7 @@ spec:
            secretName: ssl-config-batch
 {% if deploy %}
 ---
-apiVersion: autoscaling/v2beta1
+apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   name: batch
@@ -506,7 +506,9 @@ spec:
    - type: Resource
      resource:
        name: cpu
-       targetAverageUtilization: 2500
+       target:
+         type: Utilization
+         averageUtilization: 2500
 ---
 apiVersion: policy/v1
 kind: PodDisruptionBudget
diff --git a/bootstrap-gateway/deployment.yaml b/bootstrap-gateway/deployment.yaml
index 0712510a99b..bff961133ea 100644
--- a/bootstrap-gateway/deployment.yaml
+++ b/bootstrap-gateway/deployment.yaml
@@ -48,7 +48,7 @@ spec:
           - containerPort: 80
           - containerPort: 443
 ---
-apiVersion: autoscaling/v2beta1
+apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   name: gateway
@@ -63,7 +63,9 @@ spec:
    - type: Resource
      resource:
        name: cpu
-       targetAverageUtilization: 500
+       target:
+         type: Utilization
+         averageUtilization: 500
 ---
 apiVersion: policy/v1
 kind: PodDisruptionBudget
diff --git a/build.yaml b/build.yaml
index 0af6d2f4b0d..4da45283ef9 100644
--- a/build.yaml
+++ b/build.yaml
@@ -1155,6 +1155,12 @@ steps:
       mv /test-gsa-key/key.json /gsa-key/key.json
 
       export HAIL_QUERY_N_CORES=2
+      export OMP_NUM_THREADS=2
+      export OPENBLAS_NUM_THREADS=2
+      export MKL_NUM_THREADS=2
+      export VECLIB_MAXIMUM_THREADS=2
+      export NUMEXPR_NUM_THREADS=2
+
       export HAIL_TEST_RESOURCES_DIR=./resources
       export HAIL_DOCTEST_DATA_DIR=./data
       export HAIL_TEST_STORAGE_URI={{ global.test_storage_uri }}/{{ token }}
@@ -1334,6 +1340,13 @@ steps:
       sed -i 's/gsa-key/test-gsa-key/g' ${SPARK_HOME}/conf/core-site.xml
       export GOOGLE_APPLICATION_CREDENTIALS=/test-gsa-key/key.json
 
+      export HAIL_QUERY_N_CORES=2
+      export OMP_NUM_THREADS=2
+      export OPENBLAS_NUM_THREADS=2
+      export MKL_NUM_THREADS=2
+      export VECLIB_MAXIMUM_THREADS=2
+      export NUMEXPR_NUM_THREADS=2
+
       export HAIL_CLOUD={{ global.cloud }}
       export HAIL_TEST_STORAGE_URI=/io/tmp/
       export HAIL_TEST_RESOURCES_DIR=./resources
@@ -1353,7 +1366,7 @@ steps:
               --ignore=test/hailtop/ \
               --timeout=120 \
               test
-    timeout: 1200
+    timeout: 1800
     inputs:
       - from: /debug-wheel-container.tar
         to: /io/debug-wheel-container.tar
@@ -1386,6 +1399,12 @@ steps:
       python3 -m pip install --no-dependencies hail-*-py3-none-any.whl
 
       export HAIL_QUERY_N_CORES=2
+      export OMP_NUM_THREADS=2
+      export OPENBLAS_NUM_THREADS=2
+      export MKL_NUM_THREADS=2
+      export VECLIB_MAXIMUM_THREADS=2
+      export NUMEXPR_NUM_THREADS=2
+
       export PYSPARK_SUBMIT_ARGS="--driver-memory 6g pyspark-shell"
       export HAIL_LOCATION=$(dirname $(python3 -c 'import hail; print(hail.__file__)'))
 
diff --git a/gateway/deployment.yaml b/gateway/deployment.yaml
index 966bc24c1ef..9eb8e3a8f14 100644
--- a/gateway/deployment.yaml
+++ b/gateway/deployment.yaml
@@ -86,7 +86,7 @@ spec:
           configMap:
             name: gateway-xds-config
 ---
-apiVersion: autoscaling/v2beta1
+apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   name: gateway
@@ -101,7 +101,9 @@ spec:
    - type: Resource
      resource:
        name: cpu
-       targetAverageUtilization: 2500
+       target:
+         type: Utilization
+         averageUtilization: 2500
 ---
 apiVersion: policy/v1
 kind: PodDisruptionBudget
diff --git a/hail/python/test/hail/methods/test_pca.py b/hail/python/test/hail/methods/test_pca.py
index e788532cd2f..045510f68f8 100644
--- a/hail/python/test/hail/methods/test_pca.py
+++ b/hail/python/test/hail/methods/test_pca.py
@@ -261,31 +261,31 @@ def spectral_moments_helper(spec_func):
 
 
 @skip_when_service_backend(reason='v slow & OOms')
-@test_timeout(local=3 * 60)
+@test_timeout(4 * 60, batch=8 * 60)
 def test_spectral_moments_1():
     spectral_moments_helper(spec1)
 
 
 @skip_when_service_backend(reason='v slow & OOms')
-@test_timeout(local=3 * 60)
+@test_timeout(4 * 60, batch=8 * 60)
 def test_spectral_moments_2():
     spectral_moments_helper(spec2)
 
 
 @skip_when_service_backend(reason='v slow & OOms')
-@test_timeout(local=3 * 60)
+@test_timeout(4 * 60, batch=8 * 60)
 def test_spectral_moments_3():
     spectral_moments_helper(spec3)
 
 
 @skip_when_service_backend(reason='v slow & OOms')
-@test_timeout(local=3 * 60)
+@test_timeout(4 * 60, batch=8 * 60)
 def test_spectral_moments_4():
     spectral_moments_helper(spec4)
 
 
 @skip_when_service_backend(reason='v slow & OOms')
-@test_timeout(local=3 * 60)
+@test_timeout(4 * 60, batch=8 * 60)
 def test_spectral_moments_5():
     spectral_moments_helper(spec5)
 
diff --git a/hail/python/test/hail/methods/test_statgen.py b/hail/python/test/hail/methods/test_statgen.py
index 102a23bd29c..d1c1cc9a244 100644
--- a/hail/python/test/hail/methods/test_statgen.py
+++ b/hail/python/test/hail/methods/test_statgen.py
@@ -56,7 +56,7 @@ def test_impute_sex_same_as_plink(self):
     # Outside of Spark backend, "linear_regression_rows" just defers to the underscore nd version.
     linreg_functions = [hl.linear_regression_rows, hl._linear_regression_rows_nd] if backend_name == "spark" else [hl.linear_regression_rows]
 
-    @test_timeout(local=3 * 60)
+    @test_timeout(4 * 60)
     def test_linreg_basic(self):
         phenos = hl.import_table(resource('regressionLinear.pheno'),
                                  types={'Pheno': hl.tfloat64},
diff --git a/hail/python/test/hail/table/test_table.py b/hail/python/test/hail/table/test_table.py
index a6a1d8a0ed8..4b55bdfd60c 100644
--- a/hail/python/test/hail/table/test_table.py
+++ b/hail/python/test/hail/table/test_table.py
@@ -1651,7 +1651,7 @@ def test_maybe_flexindex_table_by_expr_prefix_interval_match():
 
 
 @pytest.mark.parametrize("width", [256, 512, 1024, 2048, pytest.param(3072, marks=pytest.mark.xfail(strict=True))])
-@test_timeout(3 * 60, local=6 * 60, batch=6 * 60)
+@test_timeout(6 * 60)
 def test_can_process_wide_tables(width):
     path = resource(f'width_scale_tests/{width}.tsv')
     ht = hl.import_table(path, impute=False)
diff --git a/hail/python/test/hail/vds/test_vds.py b/hail/python/test/hail/vds/test_vds.py
index 5b64c4521db..5f0fc3a6659 100644
--- a/hail/python/test/hail/vds/test_vds.py
+++ b/hail/python/test/hail/vds/test_vds.py
@@ -531,6 +531,7 @@ def test_to_dense_mt():
     assert as_dict.get(('chr22:10562436', 'NA12878')) == hl.Struct(LGT=hl.Call([0, 0]), LA=None, GQ=21, DP=9)
 
 
+@test_timeout(6 * 60)
 def test_merge_reference_blocks():
     vds = hl.vds.read_vds(os.path.join(resource('vds'), '1kg_chr22_5_samples.vds'))
     vds = hl.vds.filter_samples(vds, ['HG00187'])
diff --git a/notebook/deployment.yaml b/notebook/deployment.yaml
index 84ec1bb8f33..aac544d7c44 100644
--- a/notebook/deployment.yaml
+++ b/notebook/deployment.yaml
@@ -161,7 +161,7 @@ spec:
            optional: false
            secretName: ssl-config-notebook-python
 ---
-apiVersion: autoscaling/v2beta1
+apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   name: notebook
@@ -183,9 +183,11 @@ spec:
    - type: Resource
      resource:
        name: cpu
-       targetAverageUtilization: 2500
+       target:
+         type: Utilization
+         averageUtilization: 2500
 ---
-apiVersion: policy/v1beta1
+apiVersion: policy/v1
 kind: PodDisruptionBudget
 metadata:
   name: notebook
diff --git a/website/deployment.yaml b/website/deployment.yaml
index ba33e65c4a8..ab87aad88fd 100644
--- a/website/deployment.yaml
+++ b/website/deployment.yaml
@@ -99,7 +99,7 @@ spec:
            optional: false
            secretName: ssl-config-website
 ---
-apiVersion: autoscaling/v2beta1
+apiVersion: autoscaling/v2
 kind: HorizontalPodAutoscaler
 metadata:
   name: www
@@ -119,7 +119,9 @@ spec:
   - type: Resource
     resource:
       name: cpu
-      targetAverageUtilization: 2500
+      target:
+        type: Utilization
+        averageUtilization: 2500
 ---
 apiVersion: policy/v1
 kind: PodDisruptionBudget

From dae377875629e4469221a554f437b1648ce22430 Mon Sep 17 00:00:00 2001
From: Patrick Schultz 
Date: Fri, 21 Jul 2023 15:48:47 -0400
Subject: [PATCH 022/180] [query] reenable long dormant localize_entries tests
 (#13241)

---
 .../hail/matrixtable/test_matrix_table.py     | 30 ++++++++++---------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/hail/python/test/hail/matrixtable/test_matrix_table.py b/hail/python/test/hail/matrixtable/test_matrix_table.py
index 7328dc61fef..eaad844c746 100644
--- a/hail/python/test/hail/matrixtable/test_matrix_table.py
+++ b/hail/python/test/hail/matrixtable/test_matrix_table.py
@@ -1566,37 +1566,39 @@ def test_agg_cols_group_by(self):
         for aggregation, expected in tests:
             self.assertEqual(t.select_rows(result = aggregation).result.collect()[0], expected)
 
-    def localize_entries_with_both_none_is_rows_table(self):
+    def test_localize_entries_with_both_none_is_rows_table(self):
         mt = hl.utils.range_matrix_table(10, 10)
-        mt = mt.select_entries(x = mt.row_idx * mt.col_idx)
+        mt = mt.select_entries(x=mt.row_idx * mt.col_idx)
         localized = mt.localize_entries(entries_array_field_name=None,
                                         columns_array_field_name=None)
         rows_table = mt.rows()
-        assert rows_table.collect() == localized.collect()
-        assert rows_table.globals_table().collect() == localized.globals_table().collect()
+        assert rows_table._same(localized)
 
-    def localize_entries_with_none_cols_adds_no_globals(self):
+    def test_localize_entries_with_none_cols_adds_no_globals(self):
         mt = hl.utils.range_matrix_table(10, 10)
-        mt = mt.select_entries(x = mt.row_idx * mt.col_idx)
+        mt = mt.select_entries(x=mt.row_idx * mt.col_idx)
         localized = mt.localize_entries(entries_array_field_name=Env.get_uid(),
                                         columns_array_field_name=None)
-        assert mt.globals_table().collect() == localized.globals_table().collect()
+        assert hl.eval(mt.globals) == hl.eval(localized.globals)
 
-    def localize_entries_with_none_entries_changes_no_rows(self):
+    def test_localize_entries_with_none_entries_changes_no_rows(self):
         mt = hl.utils.range_matrix_table(10, 10)
-        mt = mt.select_entries(x = mt.row_idx * mt.col_idx)
+        mt = mt.select_entries(x=mt.row_idx * mt.col_idx)
         localized = mt.localize_entries(entries_array_field_name=None,
                                         columns_array_field_name=Env.get_uid())
         rows_table = mt.rows()
-        assert rows_table.collect() == localized.collect()
+        assert rows_table.select_globals()._same(localized.select_globals())
 
-    def localize_entries_creates_arrays_of_entries_and_array_of_cols(self):
+    def test_localize_entries_creates_arrays_of_entries_and_array_of_cols(self):
         mt = hl.utils.range_matrix_table(10, 10)
-        mt = mt.select_entries(x = mt.row_idx * mt.col_idx)
+        mt = mt.select_entries(x=mt.row_idx * mt.col_idx)
         localized = mt.localize_entries(entries_array_field_name='entries',
                                         columns_array_field_name='cols')
-        assert [[x * y for x in range(0, 10)] for y in range(0, 10)] == localized.entries.collect()
-        assert range(0, 10) == localized.cols.collect()
+        t = hl.utils.range_table(10)
+        t = t.select(entries=hl.range(10).map(lambda y: hl.struct(x=t.idx * y)))
+        t = t.select_globals(cols=hl.range(10).map(lambda y: hl.struct(col_idx=y)))
+        t = t.rename({'idx': 'row_idx'})
+        assert localized._same(t)
 
     def test_multi_write(self):
         mt = self.get_mt()

From 7f718fbeb3dfdb16497c29ee2f36fab1420e46b2 Mon Sep 17 00:00:00 2001
From: iris <84595986+iris-garden@users.noreply.github.com>
Date: Fri, 21 Jul 2023 16:59:29 -0400
Subject: [PATCH 023/180] [batch] reads `HAIL_BATCH_REGIONS` environment
 variable correctly (#13239)

`hailtop.batch.ServiceBackend` uses `get_user_config().get` to read the
`HAIL_BATCH_REGIONS` environment variable, when it should use
`configuration_of`. This change fixes that.
---
 hail/python/hailtop/batch/backend.py | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py
index 73ee9209065..e619683ab6f 100644
--- a/hail/python/hailtop/batch/backend.py
+++ b/hail/python/hailtop/batch/backend.py
@@ -16,7 +16,7 @@
 from rich.progress import track
 
 from hailtop import pip_version
-from hailtop.config import configuration_of, get_deploy_config, get_user_config, get_remote_tmpdir
+from hailtop.config import configuration_of, get_deploy_config, get_remote_tmpdir
 from hailtop.utils.rich_progress_bar import SimpleRichProgressBar
 from hailtop.utils import parse_docker_image_reference, async_to_blocking, bounded_gather, url_scheme
 from hailtop.batch.hail_genetics_images import HAIL_GENETICS_IMAGES
@@ -482,8 +482,7 @@ def __init__(self,
                 'MY_BILLING_PROJECT`')
         self._batch_client = BatchClient(billing_project, _token=token)
 
-        user_config = get_user_config()
-        self.remote_tmpdir = get_remote_tmpdir('ServiceBackend', bucket=bucket, remote_tmpdir=remote_tmpdir, user_config=user_config)
+        self.remote_tmpdir = get_remote_tmpdir('ServiceBackend', bucket=bucket, remote_tmpdir=remote_tmpdir)
 
         gcs_kwargs: Dict[str, Any]
         if google_project is not None:
@@ -502,7 +501,7 @@ def __init__(self,
         self.__fs: RouterAsyncFS = RouterAsyncFS(gcs_kwargs=gcs_kwargs)
 
         if regions is None:
-            regions_from_conf = user_config.get('batch', 'regions', fallback=None)
+            regions_from_conf = configuration_of('batch', 'regions', None, None)
             if regions_from_conf is not None:
                 assert isinstance(regions_from_conf, str)
                 regions = regions_from_conf.split(',')

From 9b835f469c4c066c664da2c9015f064d393f4ed2 Mon Sep 17 00:00:00 2001
From: jigold 
Date: Fri, 21 Jul 2023 18:44:04 -0400
Subject: [PATCH 024/180] [batch] Add feature switches (#13262)

Let me know if you think this is good and whether I need to test the UI
with dev deploy.

---------

Co-authored-by: Dan King 
---
 batch/batch/driver/main.py              | 46 ++++++++++++++++++++++++-
 batch/batch/driver/templates/index.html | 13 +++++++
 batch/sql/add-feature-flags.sql         |  5 +++
 batch/sql/delete-batch-tables.sql       |  3 +-
 batch/sql/estimated-current.sql         |  4 +++
 build.yaml                              |  3 ++
 6 files changed, 72 insertions(+), 2 deletions(-)
 create mode 100644 batch/sql/add-feature-flags.sql

diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py
index e65ddfa7953..66a466c1fb5 100644
--- a/batch/batch/driver/main.py
+++ b/batch/batch/driver/main.py
@@ -38,7 +38,14 @@
 from hailtop import aiotools, httpx
 from hailtop.config import get_deploy_config
 from hailtop.hail_logging import AccessLogger
-from hailtop.utils import AsyncWorkerPool, Notice, dump_all_stacktraces, flatten, periodically_call, time_msecs
+from hailtop.utils import (
+    AsyncWorkerPool,
+    Notice,
+    dump_all_stacktraces,
+    flatten,
+    periodically_call,
+    time_msecs,
+)
 from web_common import render_template, set_message, setup_aiohttp_jinja2, setup_common_static_routes
 
 from ..batch import cancel_batch_in_db
@@ -459,6 +466,7 @@ async def get_index(request, userdata):
         'total_provisioned_cores_mcpu': inst_coll_manager.global_total_provisioned_cores_mcpu,
         'live_free_cores_mcpu': inst_coll_manager.global_current_version_live_free_cores_mcpu,
         'frozen': app['frozen'],
+        'feature_flags': app['feature_flags'],
     }
     return await render_template('batch-driver', request, userdata, 'index.html', page_context)
 
@@ -552,6 +560,27 @@ def validate_int(session, name, value, predicate, description):
     return validate(session, name, i, predicate, description)
 
 
+@routes.post('/configure-feature-flags')
+@check_csrf_token
+@auth.web_authenticated_developers_only()
+async def configure_feature_flags(request, userdata):  # pylint: disable=unused-argument
+    app = request.app
+    db: Database = app['db']
+    post = await request.post()
+
+    compact_billing_tables = 'compact_billing_tables' in post
+
+    await db.execute_update(
+        '''
+UPDATE feature_flags SET compact_billing_tables = %s;
+''',
+        (compact_billing_tables,),
+    )
+
+    row = await db.select_and_fetchone('SELECT * FROM feature_flags')
+    app['feature_flags'] = row
+
+
 @routes.post('/config-update/pool/{pool}')
 @check_csrf_token
 @auth.web_authenticated_developers_only()
@@ -1335,6 +1364,16 @@ async def monitor_system(app):
     monitor_instances(app)
 
 
+async def compact_agg_billing_project_users_table(app):
+    if not app['feature_flags']['compact_billing_tables']:
+        return
+
+
+async def compact_agg_billing_project_users_by_date_table(app):
+    if not app['feature_flags']['compact_billing_tables']:
+        return
+
+
 async def scheduling_cancelling_bump(app):
     log.info('scheduling cancelling bump loop')
     app['scheduler_state_changed'].notify()
@@ -1412,6 +1451,9 @@ async def on_startup(app):
     app['batch_headers'] = {'Authorization': f'Bearer {row["internal_token"]}'}
     app['frozen'] = row['frozen']
 
+    row = await db.select_and_fetchone('SELECT * FROM feature_flags')
+    app['feature_flags'] = row
+
     await refresh_globals_from_db(app, db)
 
     app['scheduler_state_changed'] = Notice()
@@ -1437,6 +1479,8 @@ async def on_startup(app):
     task_manager.ensure_future(periodically_call(60, scheduling_cancelling_bump, app))
     task_manager.ensure_future(periodically_call(15, monitor_system, app))
     task_manager.ensure_future(periodically_call(5, refresh_globals_from_db, app, db))
+    task_manager.ensure_future(periodically_call(60, compact_agg_billing_project_users_table, app))
+    task_manager.ensure_future(periodically_call(60, compact_agg_billing_project_users_by_date_table, app))
 
 
 async def on_cleanup(app):
diff --git a/batch/batch/driver/templates/index.html b/batch/batch/driver/templates/index.html
index 161f0292bc2..26016670cd5 100644
--- a/batch/batch/driver/templates/index.html
+++ b/batch/batch/driver/templates/index.html
@@ -25,6 +25,19 @@ 

Globals

{% endif %}

+

Feature Flags

+
+
+ + + +
+
+

Instance Collections

Pools

diff --git a/batch/sql/add-feature-flags.sql b/batch/sql/add-feature-flags.sql new file mode 100644 index 00000000000..cb78ec627a5 --- /dev/null +++ b/batch/sql/add-feature-flags.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS `feature_flags` ( + `compact_billing_tables` BOOLEAN NOT NULL +) ENGINE = InnoDB; + +INSERT INTO `feature_flags` (compact_billing_tables) VALUES (0); diff --git a/batch/sql/delete-batch-tables.sql b/batch/sql/delete-batch-tables.sql index 754f42018c3..c59e928b6e8 100644 --- a/batch/sql/delete-batch-tables.sql +++ b/batch/sql/delete-batch-tables.sql @@ -79,4 +79,5 @@ DROP TABLE IF EXISTS `pools`; DROP TABLE IF EXISTS `inst_colls`; DROP TABLE IF EXISTS `latest_product_versions`; DROP TABLE IF EXISTS `resources`; -DROP TABLE IF EXISTS `regions` +DROP TABLE IF EXISTS `regions`; +DROP TABLE IF EXISTS `feature_flags`; diff --git a/batch/sql/estimated-current.sql b/batch/sql/estimated-current.sql index 5bdf4d430c8..2788c825321 100644 --- a/batch/sql/estimated-current.sql +++ b/batch/sql/estimated-current.sql @@ -5,6 +5,10 @@ CREATE TABLE IF NOT EXISTS `globals` ( `frozen` BOOLEAN NOT NULL DEFAULT FALSE ) ENGINE = InnoDB; +CREATE TABLE IF NOT EXISTS `feature_flags` ( + `compact_billing_tables` BOOLEAN NOT NULL +) ENGINE = InnoDB; + CREATE TABLE IF NOT EXISTS `resources` ( `resource` VARCHAR(100) NOT NULL, `rate` DOUBLE NOT NULL, diff --git a/build.yaml b/build.yaml index 4da45283ef9..a0c1dbcc3a5 100644 --- a/build.yaml +++ b/build.yaml @@ -2301,6 +2301,9 @@ steps: - name: add-list-batches-index script: /io/sql/add-list-batches-index.sql online: true + - name: add-feature-flags + script: /io/sql/add-feature-flags.sql + online: true inputs: - from: /repo/batch/sql to: /io/sql From 18c4d53ebf02cc37e4b176e2f83dd50cdd3491e4 Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Fri, 21 Jul 2023 21:22:38 -0400 Subject: [PATCH 025/180] [query] use nPartitions arg of KeyByAndAgg in lowered impl (#13264) Bug reported by https://discuss.hail.is/t/no-change-with-partition-hint/3497/2 --- .../src/main/scala/is/hail/backend/Backend.scala | 16 +++++++++++++--- .../is/hail/backend/local/LocalBackend.scala | 5 +++-- .../is/hail/backend/service/ServiceBackend.scala | 5 +++-- .../is/hail/backend/spark/SparkBackend.scala | 5 +++-- .../ir/lowering/LowerAndExecuteShuffles.scala | 3 ++- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/hail/src/main/scala/is/hail/backend/Backend.scala b/hail/src/main/scala/is/hail/backend/Backend.scala index 8265f66fdd9..3abbac86b69 100644 --- a/hail/src/main/scala/is/hail/backend/Backend.scala +++ b/hail/src/main/scala/is/hail/backend/Backend.scala @@ -86,18 +86,28 @@ abstract class Backend { ctx: ExecuteContext, stage: TableStage, sortFields: IndexedSeq[SortField], - rt: RTable + rt: RTable, + nPartitions: Option[Int] ): TableReader final def lowerDistributedSort( ctx: ExecuteContext, - inputIR: TableIR, + stage: TableStage, sortFields: IndexedSeq[SortField], rt: RTable + ): TableReader = + lowerDistributedSort(ctx, stage, sortFields, rt, None) + + final def lowerDistributedSort( + ctx: ExecuteContext, + inputIR: TableIR, + sortFields: IndexedSeq[SortField], + rt: RTable, + nPartitions: Option[Int] = None ): TableReader = { val analyses = LoweringAnalyses.apply(inputIR, ctx) val inputStage = tableToTableStage(ctx, inputIR, analyses) - lowerDistributedSort(ctx, inputStage, sortFields, rt) + lowerDistributedSort(ctx, inputStage, sortFields, rt, nPartitions) } def tableToTableStage(ctx: ExecuteContext, diff --git a/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala b/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala index 6deb9bf54a9..5daa3a4a50b 100644 --- a/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala +++ b/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala @@ -317,10 +317,11 @@ class LocalBackend( ctx: ExecuteContext, stage: TableStage, sortFields: IndexedSeq[SortField], - rt: RTable + rt: RTable, + nPartitions: Option[Int] ): TableReader = { - LowerDistributedSort.distributedSort(ctx, stage, sortFields, rt) + LowerDistributedSort.distributedSort(ctx, stage, sortFields, rt, nPartitions) } def pyLoadReferencesFromDataset(path: String): String = { diff --git a/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala b/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala index 42bbea1df6d..7136ed7e534 100644 --- a/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala +++ b/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala @@ -353,8 +353,9 @@ class ServiceBackend( ctx: ExecuteContext, inputStage: TableStage, sortFields: IndexedSeq[SortField], - rt: RTable - ): TableReader = LowerDistributedSort.distributedSort(ctx, inputStage, sortFields, rt) + rt: RTable, + nPartitions: Option[Int] + ): TableReader = LowerDistributedSort.distributedSort(ctx, inputStage, sortFields, rt, nPartitions) def persist(backendContext: BackendContext, id: String, value: BlockMatrix, storageLevel: String): Unit = ??? diff --git a/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala b/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala index 23214020a1e..2d56613d146 100644 --- a/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala +++ b/hail/src/main/scala/is/hail/backend/spark/SparkBackend.scala @@ -680,7 +680,8 @@ class SparkBackend( ctx: ExecuteContext, stage: TableStage, sortFields: IndexedSeq[SortField], - rt: RTable + rt: RTable, + nPartitions: Option[Int] ): TableReader = { if (getFlag("use_new_shuffle") != null) return LowerDistributedSort.distributedSort(ctx, stage, sortFields, rt) @@ -705,7 +706,7 @@ class SparkBackend( val act = implicitly[ClassTag[Annotation]] val codec = TypedCodecSpec(rvd.rowPType, BufferSpec.wireSpec) - val rdd = rvd.keyedEncodedRDD(ctx, codec, sortFields.map(_.field)).sortBy(_._1)(ord, act) + val rdd = rvd.keyedEncodedRDD(ctx, codec, sortFields.map(_.field)).sortBy(_._1, numPartitions = nPartitions.getOrElse(rvd.getNumPartitions))(ord, act) val (rowPType: PStruct, orderedCRDD) = codec.decodeRDD(ctx, rowType, rdd.map(_._2)) RVDTableReader(RVD.unkeyed(rowPType, orderedCRDD), globalsLit, rt) } diff --git a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerAndExecuteShuffles.scala b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerAndExecuteShuffles.scala index 60ec2d461c6..54b27262ef3 100644 --- a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerAndExecuteShuffles.scala +++ b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerAndExecuteShuffles.scala @@ -69,7 +69,8 @@ object LowerAndExecuteShuffles { val partiallyAggregatedReader = ctx.backend.lowerDistributedSort(ctx, preShuffleStage, newKeyType.fieldNames.map(k => SortField(k, Ascending)), - rt) + rt, + nPartitions) val takeVirtualSig = TakeStateSig(VirtualTypeWithReq(newKeyType, rt.rowType.select(newKeyType.fieldNames))) val takeAggSig = PhysicalAggSig(Take(), takeVirtualSig) From bcc9046bf6e7df086213b23c10bf1337a718dc2a Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 21 Jul 2023 23:02:52 -0400 Subject: [PATCH 026/180] [query] back off spectral moments timeout for local, spark, and batch (#13278) Replaces https://github.com/hail-is/hail/pull/13260. - `test_spectral_moments` times out in a PR: (QoB) https://hail.zulipchat.com/#narrow/stream/127527-team/topic/timeouts/near/376698259, (spark) https://ci.hail.is/batches/7653376/jobs/74, (spark) https://ci.hail.is/batches/7653376/jobs/72, (spark) https://ci.hail.is/batches/7653376/jobs/62 I also backed local off to 4m even though it has no evidence of time outs. Seems simpler for Spark and local to be the same. From 6daed0e58027d12d50b4fd454b38b629e385b3ff Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 25 Jul 2023 09:30:23 -0400 Subject: [PATCH 027/180] [batch] Fix missing UI checkbox label for feature flags (#13288) Some context: To make Batch feature additions safer, we now have infrastructure to turn off new components with checkboxes on the driver page. I forgot to add the text before the checkbox when I put it in last week. --- batch/batch/driver/templates/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/batch/batch/driver/templates/index.html b/batch/batch/driver/templates/index.html index 26016670cd5..9840f6211e5 100644 --- a/batch/batch/driver/templates/index.html +++ b/batch/batch/driver/templates/index.html @@ -29,6 +29,7 @@

Feature Flags

+ Date: Tue, 25 Jul 2023 15:37:18 -0400 Subject: [PATCH 028/180] [batch] Fix feature-flags UI on driver page (#13290) --- batch/batch/driver/main.py | 2 ++ batch/batch/driver/templates/index.html | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 66a466c1fb5..fa609ea8bf7 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -580,6 +580,8 @@ async def configure_feature_flags(request, userdata): # pylint: disable=unused- row = await db.select_and_fetchone('SELECT * FROM feature_flags') app['feature_flags'] = row + return web.HTTPFound(deploy_config.external_url('batch-driver', '/')) + @routes.post('/config-update/pool/{pool}') @check_csrf_token diff --git a/batch/batch/driver/templates/index.html b/batch/batch/driver/templates/index.html index 9840f6211e5..96a447cb92d 100644 --- a/batch/batch/driver/templates/index.html +++ b/batch/batch/driver/templates/index.html @@ -35,7 +35,9 @@

Feature Flags

name="compact_billing_tables" {% if feature_flags['compact_billing_tables'] %}checked{% endif %} value="true" /> - +
+ +
From 4d583cc39a27340f614f3e15b4117cb99965480e Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 25 Jul 2023 18:16:19 -0400 Subject: [PATCH 029/180] [tests] Increase service backend test timeout to 600s (#13297) --- build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.yaml b/build.yaml index a0c1dbcc3a5..1cebe54d38e 100644 --- a/build.yaml +++ b/build.yaml @@ -2511,7 +2511,7 @@ steps: --instafail \ --durations=50 \ --ignore=test/hailtop/ \ - --timeout=300 \ + --timeout=600 \ test timeout: 2700 inputs: From 5326b011c7db2d1722fee88a6b12b0ea4fff9ea2 Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 25 Jul 2023 19:13:43 -0400 Subject: [PATCH 030/180] [batch] Add feature flag for oms agent (#13293) --- .../cloud/azure/driver/create_instance.py | 52 +++++++++++-------- batch/batch/cloud/azure/driver/driver.py | 2 +- .../cloud/azure/driver/resource_manager.py | 3 ++ batch/batch/driver/main.py | 5 +- batch/batch/driver/templates/index.html | 6 +++ batch/sql/add-oms-agent-flag.sql | 1 + batch/sql/estimated-current.sql | 3 +- build.yaml | 3 ++ 8 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 batch/sql/add-oms-agent-flag.sql diff --git a/batch/batch/cloud/azure/driver/create_instance.py b/batch/batch/cloud/azure/driver/create_instance.py index 70444c02168..a24484fdc11 100644 --- a/batch/batch/cloud/azure/driver/create_instance.py +++ b/batch/batch/cloud/azure/driver/create_instance.py @@ -41,6 +41,7 @@ def create_vm_config( ssh_public_key: str, max_price: Optional[float], instance_config: InstanceConfig, + feature_flags: dict, ) -> dict: _, cores = azure_machine_type_to_worker_type_and_cores(machine_type) @@ -317,6 +318,33 @@ def create_vm_config( tags = {'namespace': DEFAULT_NAMESPACE, 'batch-worker': '1'} + vm_resources = [] + + if feature_flags['oms_agent']: + vm_resources.append( + { + 'apiVersion': '2018-06-01', + 'type': 'extensions', + 'name': 'OMSExtension', + 'location': "[parameters('location')]", + 'tags': tags, + 'dependsOn': ["[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"], + 'properties': { + 'publisher': 'Microsoft.EnterpriseCloud.Monitoring', + 'type': 'OmsAgentForLinux', + 'typeHandlerVersion': '1.13', + 'autoUpgradeMinorVersion': False, + 'enableAutomaticUpgrade': False, + 'settings': { + 'workspaceId': "[reference(resourceId('Microsoft.OperationalInsights/workspaces/', parameters('workspaceName')), '2015-03-20').customerId]" + }, + 'protectedSettings': { + 'workspaceKey': "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces/', parameters('workspaceName')), '2015-03-20').primarySharedKey]" + }, + }, + }, + ) + vm_config: Dict[str, Any] = { 'apiVersion': '2021-03-01', 'type': 'Microsoft.Compute/virtualMachines', @@ -369,29 +397,7 @@ def create_vm_config( }, 'userData': "[parameters('userData')]", }, - 'resources': [ - { - 'apiVersion': '2018-06-01', - 'type': 'extensions', - 'name': 'OMSExtension', - 'location': "[parameters('location')]", - 'tags': tags, - 'dependsOn': ["[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'))]"], - 'properties': { - 'publisher': 'Microsoft.EnterpriseCloud.Monitoring', - 'type': 'OmsAgentForLinux', - 'typeHandlerVersion': '1.13', - 'autoUpgradeMinorVersion': False, - 'enableAutomaticUpgrade': False, - 'settings': { - 'workspaceId': "[reference(resourceId('Microsoft.OperationalInsights/workspaces/', parameters('workspaceName')), '2015-03-20').customerId]" - }, - 'protectedSettings': { - 'workspaceKey': "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces/', parameters('workspaceName')), '2015-03-20').primarySharedKey]" - }, - }, - }, - ], + 'resources': vm_resources, } properties = vm_config['properties'] diff --git a/batch/batch/cloud/azure/driver/driver.py b/batch/batch/cloud/azure/driver/driver.py index 797a1610cc2..9256e7f8033 100644 --- a/batch/batch/cloud/azure/driver/driver.py +++ b/batch/batch/cloud/azure/driver/driver.py @@ -67,7 +67,7 @@ async def create( billing_manager = await AzureBillingManager.create(db, pricing_client, regions) inst_coll_manager = InstanceCollectionManager(db, machine_name_prefix, region_monitor, region, regions) resource_manager = AzureResourceManager( - subscription_id, resource_group, ssh_public_key, arm_client, compute_client, billing_manager + app, subscription_id, resource_group, ssh_public_key, arm_client, compute_client, billing_manager ) create_pools_coros = [ diff --git a/batch/batch/cloud/azure/driver/resource_manager.py b/batch/batch/cloud/azure/driver/resource_manager.py index e792f64f53a..67109dcfb4e 100644 --- a/batch/batch/cloud/azure/driver/resource_manager.py +++ b/batch/batch/cloud/azure/driver/resource_manager.py @@ -40,6 +40,7 @@ def parse_azure_timestamp(timestamp: Optional[str]) -> Optional[int]: class AzureResourceManager(CloudResourceManager): def __init__( self, + app, subscription_id: str, resource_group: str, ssh_public_key: str, @@ -47,6 +48,7 @@ def __init__( compute_client: aioazure.AzureComputeClient, # BORROWED billing_manager: AzureBillingManager, ): + self.app = app self.subscription_id = subscription_id self.resource_group = resource_group self.ssh_public_key = ssh_public_key @@ -177,6 +179,7 @@ async def create_vm( self.ssh_public_key, max_price, instance_config, + self.app['feature_flags'], ) memory_mib = azure_worker_memory_per_core_mib(worker_type) * cores diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index fa609ea8bf7..3690028edad 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -569,12 +569,13 @@ async def configure_feature_flags(request, userdata): # pylint: disable=unused- post = await request.post() compact_billing_tables = 'compact_billing_tables' in post + oms_agent = 'oms_agent' in post await db.execute_update( ''' -UPDATE feature_flags SET compact_billing_tables = %s; +UPDATE feature_flags SET compact_billing_tables = %s, oms_agent = %s; ''', - (compact_billing_tables,), + (compact_billing_tables, oms_agent), ) row = await db.select_and_fetchone('SELECT * FROM feature_flags') diff --git a/batch/batch/driver/templates/index.html b/batch/batch/driver/templates/index.html index 96a447cb92d..11e582773c8 100644 --- a/batch/batch/driver/templates/index.html +++ b/batch/batch/driver/templates/index.html @@ -35,6 +35,12 @@

Feature Flags

name="compact_billing_tables" {% if feature_flags['compact_billing_tables'] %}checked{% endif %} value="true" /> + +
diff --git a/batch/sql/add-oms-agent-flag.sql b/batch/sql/add-oms-agent-flag.sql new file mode 100644 index 00000000000..5e7f0539aae --- /dev/null +++ b/batch/sql/add-oms-agent-flag.sql @@ -0,0 +1 @@ +ALTER TABLE `feature_flags` ADD COLUMN `oms_agent` BOOLEAN NOT NULL DEFAULT TRUE; diff --git a/batch/sql/estimated-current.sql b/batch/sql/estimated-current.sql index 2788c825321..423a2be8035 100644 --- a/batch/sql/estimated-current.sql +++ b/batch/sql/estimated-current.sql @@ -6,7 +6,8 @@ CREATE TABLE IF NOT EXISTS `globals` ( ) ENGINE = InnoDB; CREATE TABLE IF NOT EXISTS `feature_flags` ( - `compact_billing_tables` BOOLEAN NOT NULL + `compact_billing_tables` BOOLEAN NOT NULL, + `oms_agent` BOOLEAN NOT NULL DEFAULT TRUE ) ENGINE = InnoDB; CREATE TABLE IF NOT EXISTS `resources` ( diff --git a/build.yaml b/build.yaml index 1cebe54d38e..0d7a0b6d4da 100644 --- a/build.yaml +++ b/build.yaml @@ -2304,6 +2304,9 @@ steps: - name: add-feature-flags script: /io/sql/add-feature-flags.sql online: true + - name: add-oms-agent-flag + script: /io/sql/add-oms-agent-flag.sql + online: true inputs: - from: /repo/batch/sql to: /io/sql From 8db23d7b4c2db9dd79953939e727ce244eb812e7 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 26 Jul 2023 21:41:45 -0400 Subject: [PATCH 031/180] [auth] Deleting users in test auth should not delete any namespaces (#13315) --- auth/auth/driver/driver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auth/auth/driver/driver.py b/auth/auth/driver/driver.py index daa6a4ebe9d..cd8b7e6e292 100644 --- a/auth/auth/driver/driver.py +++ b/auth/auth/driver/driver.py @@ -486,7 +486,8 @@ async def delete_user(app, user): await hail_identity_secret.delete() namespace_name = user['namespace_name'] - if namespace_name is not None and namespace_name != DEFAULT_NAMESPACE: + # auth services in test namespaces cannot/should not be creating and deleting namespaces + if namespace_name is not None and namespace_name != DEFAULT_NAMESPACE and not is_test_deployment: assert user['is_developer'] == 1 # don't bother deleting database-server-config since we're From ecf4cdc4860b5505e6093251ae263cf0bab45d27 Mon Sep 17 00:00:00 2001 From: jigold Date: Thu, 27 Jul 2023 03:19:51 -0400 Subject: [PATCH 032/180] [batch] Increase max worker idle time to 2 mins in test and dev (#13314) I observed a cluster with it set to the default idle time of 30 seconds in Azure and the workers were continuously thrashing leading up to 49 instances being created over the course of a PR. With an idle time of 120 seconds, there was no thrashing and 28 instances were created over the course of the PR (16 standard + job private etc.). The cluster nicely scaled down at the end of the PR. It looked like a couple of times the `standard-np` pool scaled up and then scaled down so I assume the `standard` pool wasn't at full capacity while that was happening. It might be worth configuring the `standard-np` pool to be 4 or 5 standing instances with 16 cores and see what happens -- that might help as well. --- batch/sql/increase_test_max_idle_time.py | 23 +++++++++++++++++++++++ build.yaml | 3 +++ 2 files changed, 26 insertions(+) create mode 100644 batch/sql/increase_test_max_idle_time.py diff --git a/batch/sql/increase_test_max_idle_time.py b/batch/sql/increase_test_max_idle_time.py new file mode 100644 index 00000000000..0329031567b --- /dev/null +++ b/batch/sql/increase_test_max_idle_time.py @@ -0,0 +1,23 @@ +import os +import asyncio +from gear import Database + + +async def main(): + if os.environ['HAIL_SCOPE'] == 'deploy': + return + + db = Database() + await db.async_init() + + await db.execute_update( + ''' +UPDATE inst_colls +SET worker_max_idle_time_secs = 120 +''') + + await db.async_close() + + +loop = asyncio.get_event_loop() +loop.run_until_complete(main()) diff --git a/build.yaml b/build.yaml index 0d7a0b6d4da..6fbbb5c7d18 100644 --- a/build.yaml +++ b/build.yaml @@ -2307,6 +2307,9 @@ steps: - name: add-oms-agent-flag script: /io/sql/add-oms-agent-flag.sql online: true + - name: increase-test-max-idle-time + script: /io/sql/increase_test_max_idle_time.py + online: true inputs: - from: /repo/batch/sql to: /io/sql From ff5d66a68358f662a9f63fd8fd4daa577e70316e Mon Sep 17 00:00:00 2001 From: iris <84595986+iris-garden@users.noreply.github.com> Date: Thu, 27 Jul 2023 10:00:56 -0400 Subject: [PATCH 033/180] [infra] updates bootstrap dependencies script to use make target (#13251) --- infra/install_bootstrap_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/install_bootstrap_dependencies.sh b/infra/install_bootstrap_dependencies.sh index 437dabc1114..40ed89c0772 100755 --- a/infra/install_bootstrap_dependencies.sh +++ b/infra/install_bootstrap_dependencies.sh @@ -14,4 +14,4 @@ sudo snap install --classic kubectl sudo usermod -a -G docker $USER python3 -m pip install --upgrade pip -python3 -m pip install -r $HOME/hail/docker/requirements.txt +make -C $HOME/hail install-dev-requirements From bf57511abbdd4a33efca3ab10571f309d066151c Mon Sep 17 00:00:00 2001 From: jigold Date: Thu, 27 Jul 2023 11:26:27 -0400 Subject: [PATCH 034/180] [hailtop.batch] UI Advanced Search Help Documentation (#13233) This PR should go in after #13199. --- .../batch/docs/advanced_search_help.rst | 176 ++++++++++++++++++ hail/python/hailtop/batch/docs/index.rst | 1 + hail/python/hailtop/batch/docs/service.rst | 3 + 3 files changed, 180 insertions(+) create mode 100644 hail/python/hailtop/batch/docs/advanced_search_help.rst diff --git a/hail/python/hailtop/batch/docs/advanced_search_help.rst b/hail/python/hailtop/batch/docs/advanced_search_help.rst new file mode 100644 index 00000000000..83f2594c3fe --- /dev/null +++ b/hail/python/hailtop/batch/docs/advanced_search_help.rst @@ -0,0 +1,176 @@ +.. _sec-advanced_search_help: + +==================== +Advanced Search Help +==================== + +A query has one statement per line. A statement is one of the expressions (exact match, +partial match, keyword, or predefined keyword) listed below. When the query is run, each +statement will be joined to the next with the ``AND`` operator. + +Exact Match Expression +---------------------- + +A single word enclosed with double quotes that is an exact match for either the name or +value of an attribute. + +**Example:** ``“pca_pipeline”`` + +Partial Match Expression +------------------------ + +A single word without any quotes that is a partial match for either the name or the value +of an attribute. + +**Example:** ``pipe`` + +Keyword Expression +------------------ + +The left hand side of the statement is the name of the attribute and the right hand side +is the value to search against. Allowed operators are ``=``, ``==``, ``!=``, ``=~``, and +``!~`` where the operators with tildes are looking for partial matches. + +**Example:** ``name = pca_pipeline`` + +**Example:** ``name =~ pca`` + +Predefined Keyword Expression +----------------------------- + +The left hand side of the statement is a special Batch-specific keyword which can be one of the values +listed in the tables below. Allowed operators are dependent on the type of the value expected for each +keyword, but can be one of ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=``, ``=~``, ``!~``. +The right hand side is the value to search against. + +.. list-table:: Keywords + :widths: 25 25 50 50 + :header-rows: 1 + + * - Keyword + - Value Type + - Allowed Operators + - Extra + * - cost + - float + - ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=`` + - + * - duration + - float + - ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=`` + - Values are rounded to the millisecond + * - start_time + - date + - ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=`` + - ISO-8601 datetime string + * - end_time + - date + - ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=`` + - ISO-8601 datetime string + + +**Example:** ``cost >= 1.00`` + +**Example:** ``duration > 5`` + +**Example:** ``start_time >= 2023-02-24T17:15:25Z`` + + +.. list-table:: Keywords specific to searching for batches + :widths: 25 25 50 50 + :header-rows: 1 + + * - Keyword + - Value Type + - Allowed Operators + - Extra + * - batch_id + - int + - ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=`` + - + * - state + - str + - ``=``, ``==``, ``!=`` + - Allowed values are `running`, `complete`, `success`, `failure`, `cancelled`, `open`, `closed` + * - user + - str + - ``=``, ``==``, ``!=``, ``=~``, ``!~`` + - + * - billing_project + - str + - ``=``, ``==``, ``!=``, ``=~``, ``!~`` + - + + +**Example:** ``state = running`` + +**Example:** ``user = johndoe`` + +**Example:** ``billing_project = johndoe-trial`` + + + +.. list-table:: Keywords specific to searching for jobs in a batch + :widths: 25 25 50 50 + :header-rows: 1 + + * - Keyword + - Value Type + - Allowed Operators + - Extra + * - job_id + - int + - ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=`` + - + * - state + - str + - ``=``, ``==``, ``!=`` + - Allowed values are `pending`, `ready`, `creating`, `running`, `live`, `cancelled`, `error`, `failed`, `bad`, `success`, `done` + * - instance + - str + - ``=``, ``==``, ``!=``, ``=~``, ``!~`` + - use this to search for all jobs that ran on a given worker + * - instance_collection + - str + - ``=``, ``==``, ``!=``, ``=~``, ``!~`` + - use this to search for all jobs in a given pool + + +**Example:** ``user = johndoe`` + +**Example:** ``billing_project = johndoe-trial`` + +**Example:** ``instance_collection = standard`` + + +Combining Multiple Statements +----------------------------- + +**Example:** Searching for batches in a time window + +.. code-block:: + + start_time >= 2023-02-24T17:15:25Z + end_time <= 2023-07-01T12:35:00Z + +**Example:** Searching for batches that have run since June 2023 that cost more than $5 submitted by a given user + +.. code-block:: + + start_time >= 2023-06-01 + cost > 5.00 + user = johndoe + +**Example:** Searching for failed batches where the batch name contains pca + +.. code-block:: + + state = failed + name =~ pca + +**Example:** Searching for jobs within a given range of ids + +.. code-block:: + + job_id >= 1000 + job_id < 2000 diff --git a/hail/python/hailtop/batch/docs/index.rst b/hail/python/hailtop/batch/docs/index.rst index 6650d3a38ac..b5f4e21ff8a 100644 --- a/hail/python/hailtop/batch/docs/index.rst +++ b/hail/python/hailtop/batch/docs/index.rst @@ -22,6 +22,7 @@ Contents Batch Service Cookbooks Reference (Python API) + Advanced UI Search Help Change Log And Version Policy diff --git a/hail/python/hailtop/batch/docs/service.rst b/hail/python/hailtop/batch/docs/service.rst index 97e8258530d..5b50a6b0e74 100644 --- a/hail/python/hailtop/batch/docs/service.rst +++ b/hail/python/hailtop/batch/docs/service.rst @@ -313,6 +313,9 @@ button next to the row for that batch. You can also delete a batch with the "Del Deleting a batch only removes it from the UI. You will still be billed for a deleted batch. +The UI has an advanced search mode with a custom query language to find batches and jobs. +Learn more on the :ref:`Advanced Search Help ` page. + Important Notes --------------- From c74530ddc516e7c5febd3b120e8e9c18c4f00fb3 Mon Sep 17 00:00:00 2001 From: iris <84595986+iris-garden@users.noreply.github.com> Date: Thu, 27 Jul 2023 13:38:18 -0400 Subject: [PATCH 035/180] [query] removes unnecessary serialization in is.hail.rvd.RVD.localSort (#13313) On the current release (0.2.119), `is.hail.rvd.RVD.localSort` attempts to serialize an entire `is.hail.rvd.RVD` object when called, which causes some operations, like reading a set of VCF files, to fail. That particular operation no longer fails due to some combination of the changes made to reading VCF files in https://github.com/hail-is/hail/pull/13206 and https://github.com/hail-is/hail/pull/13229, but the serialization could still cause issues if `is.hail.rvd.RVD.localSort` is called in another context. See https://hail.zulipchat.com/#narrow/stream/123011-Hail-Query-Dev/topic/Possible.20bug.20in.20Hail.200.2E2.2E119/near/378610151 for more information. --- hail/python/test/hail/methods/test_impex.py | 11 +++++++++-- hail/src/main/scala/is/hail/rvd/RVD.scala | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/hail/python/test/hail/methods/test_impex.py b/hail/python/test/hail/methods/test_impex.py index 74b8cf0c5ee..0ded82bc366 100644 --- a/hail/python/test/hail/methods/test_impex.py +++ b/hail/python/test/hail/methods/test_impex.py @@ -35,6 +35,11 @@ _FLOAT_ARRAY_INFO_FIELDS = ['AF', 'MLEAF'] +def _vcf_unsorted_alleles(): + mt = hl.import_vcf(resource('sample.pksorted.vcf'), n_partitions=4) + mt.rows()._force_count() + + class VCFTests(unittest.TestCase): def test_info_char(self): self.assertEqual(hl.import_vcf(resource('infochar.vcf')).count_rows(), 1) @@ -208,8 +213,10 @@ def test_import_vcf_missing_format_field_elements(self): self.assertTrue(mt.entries()._same(expected)) def test_vcf_unsorted_alleles(self): - mt = hl.import_vcf(resource('sample.pksorted.vcf'), n_partitions=4) - mt.rows()._force_count() + _vcf_unsorted_alleles() + + def test_vcf_unsorted_alleles_no_codegen(self): + with_flags(no_whole_stage_codegen="1")(_vcf_unsorted_alleles)() def test_import_vcf_skip_invalid_loci(self): mt = hl.import_vcf(resource('skip_invalid_loci.vcf'), reference_genome='GRCh37', diff --git a/hail/src/main/scala/is/hail/rvd/RVD.scala b/hail/src/main/scala/is/hail/rvd/RVD.scala index a033d309b79..a23599256bc 100644 --- a/hail/src/main/scala/is/hail/rvd/RVD.scala +++ b/hail/src/main/scala/is/hail/rvd/RVD.scala @@ -392,8 +392,9 @@ class RVD( require(partitioner.satisfiesAllowedOverlap(typ.key.length - 1)) val localTyp = typ + val localSm = partitioner.sm val sortedRDD = crdd.toCRDDRegionValue.cmapPartitions { (consumerCtx, it) => - OrderedRVIterator(localTyp, it, consumerCtx, partitioner.sm).localKeySort(newKey) + OrderedRVIterator(localTyp, it, consumerCtx, localSm).localKeySort(newKey) }.toCRDDPtr val newType = typ.copy(key = newKey) From be37cb8f34e304922bb9be940857fcfdb4f63c95 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Thu, 27 Jul 2023 16:56:26 -0500 Subject: [PATCH 036/180] [batch] Support python 3.11 in default python jobs (#13310) Co-authored-by: Daniel Goldstein --- docker/hailgenetics/Makefile | 4 ++-- docker/hailgenetics/mirror_images.sh | 2 ++ docker/hailgenetics/python-dill/Dockerfile | 4 ++-- docker/hailgenetics/python-dill/push.sh | 7 ++++--- hail/python/hailtop/batch/backend.py | 4 ++-- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/docker/hailgenetics/Makefile b/docker/hailgenetics/Makefile index cf780af1a27..f839e2af3be 100644 --- a/docker/hailgenetics/Makefile +++ b/docker/hailgenetics/Makefile @@ -1,9 +1,9 @@ include ../../config.mk -.PHONY: publish-python-dill +.PHONY: publish-python-dill mirror-dockerhub-images publish-python-dill: - DOCKER_PREFIX=$(DOCKER_PREFIX) bash python-dill/push.sh + bash python-dill/push.sh mirror-dockerhub-images: DOCKER_PREFIX=$(DOCKER_PREFIX) \ diff --git a/docker/hailgenetics/mirror_images.sh b/docker/hailgenetics/mirror_images.sh index 7c001fe8331..d3765ca91b8 100755 --- a/docker/hailgenetics/mirror_images.sh +++ b/docker/hailgenetics/mirror_images.sh @@ -38,6 +38,8 @@ images=( "python-dill:3.9-slim" "python-dill:3.10" "python-dill:3.10-slim" + "python-dill:3.11" + "python-dill:3.11-slim" "hail:${HAIL_PIP_VERSION}" "hailtop:${HAIL_PIP_VERSION}" "vep-grch37-85:${HAIL_PIP_VERSION}" diff --git a/docker/hailgenetics/python-dill/Dockerfile b/docker/hailgenetics/python-dill/Dockerfile index d42ddf99b5f..b474f2d0626 100644 --- a/docker/hailgenetics/python-dill/Dockerfile +++ b/docker/hailgenetics/python-dill/Dockerfile @@ -1,8 +1,8 @@ ARG PYTHON_VERSION FROM python:${PYTHON_VERSION} -RUN pip install --upgrade --no-cache-dir dill numpy scipy sklearn && \ +RUN pip install --upgrade --no-cache-dir dill numpy scipy scikit-learn && \ python3 -m pip check && \ apt-get update && \ apt-get install -y \ - libopenblas-base \ + libopenblas0 \ && rm -rf /var/lib/apt/lists/* diff --git a/docker/hailgenetics/python-dill/push.sh b/docker/hailgenetics/python-dill/push.sh index 4d79c97a322..c2b4dec98de 100644 --- a/docker/hailgenetics/python-dill/push.sh +++ b/docker/hailgenetics/python-dill/push.sh @@ -1,14 +1,15 @@ #!/bin/bash - +cd $(dirname $0) set -ex -for version in 3.8 3.8-slim 3.9 3.9-slim 3.10 3.10-slim +for version in 3.8 3.8-slim 3.9 3.9-slim 3.10 3.10-slim 3.11 3.11-slim do public=hailgenetics/python-dill:$version DOCKER_BUILDKIT=1 docker build \ + --platform linux/amd64 \ --build-arg PYTHON_VERSION=$version \ - --file Dockerfile.out \ + --file Dockerfile \ --build-arg BUILDKIT_INLINE_CACHE=1 \ --tag ${public} \ . diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index e619683ab6f..c95e7af53da 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -649,9 +649,9 @@ def symlink_input_resource_group(r): for pyjob in pyjobs: if pyjob._image is None: version = sys.version_info - if version.major != 3 or version.minor not in (8, 9, 10): + if version.major != 3 or version.minor not in (8, 9, 10, 11): raise BatchException( - f"You must specify 'image' for Python jobs if you are using a Python version other than 3.8, 3.9 or 3.10 (you are using {version})") + f"You must specify 'image' for Python jobs if you are using a Python version other than 3.8, 3.9, 3.10, or 3.11 (you are using {version})") pyjob._image = f'hailgenetics/python-dill:{version.major}.{version.minor}-slim' await batch._serialize_python_functions_to_input_files( From f00f916faf783b89cc2fc00bfc3e39df5485d8b0 Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 27 Jul 2023 18:56:16 -0400 Subject: [PATCH 037/180] [release] 0.2.120 (#13265) --- hail/Makefile | 2 +- hail/python/hail/docs/change_log.md | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/hail/Makefile b/hail/Makefile index a6aede97073..dabe146d3a1 100644 --- a/hail/Makefile +++ b/hail/Makefile @@ -14,7 +14,7 @@ BRANCH := $(shell git rev-parse --abbrev-ref HEAD) SCALA_VERSION ?= 2.12.15 SPARK_VERSION ?= 3.3.0 HAIL_MAJOR_MINOR_VERSION := 0.2 -HAIL_PATCH_VERSION := 119 +HAIL_PATCH_VERSION := 120 HAIL_PIP_VERSION := $(HAIL_MAJOR_MINOR_VERSION).$(HAIL_PATCH_VERSION) HAIL_VERSION := $(HAIL_PIP_VERSION)-$(SHORT_REVISION) ELASTIC_MAJOR_VERSION ?= 7 diff --git a/hail/python/hail/docs/change_log.md b/hail/python/hail/docs/change_log.md index 5e6da36bf28..2f1ff73336e 100644 --- a/hail/python/hail/docs/change_log.md +++ b/hail/python/hail/docs/change_log.md @@ -33,6 +33,28 @@ Please note that **forward compatibility should not be expected, especially relating to file formats**: this means that it may not be possible to use an earlier version of Hail to read files written in a later version. +## Version 0.2.120 + +Released 2023-07-20 + +### New Features +- (hail#13206) The VDS Combiner now works in Query-on-Batch. + +### Bug Fixes +- (hail#13313) Fix bug introduced in 0.2.119 which causes a serialization error when using + Query-on-Spark to read a VCF which is sorted by locus, with split multi-allelics, in which the + records sharing a single locus do not appear in the dictionary ordering of their alternate + alleles. +- (hail#13264) Fix bug which ignored the `partition_hint` of a Table group-by-and-aggregate. +- (hail#13239) Fix bug which ignored the `HAIL_BATCH_REGIONS` argument when determining in which + regions to schedule jobs when using Query-on-Batch. +- (hail#13253) Improve `hadoop_ls` and `hfs.ls` to quickly list globbed files in a directory. The + speed improvement is proportional to the number of files in the directory. +- (hail#13226) Fix the comparison of an `hl.Struct` to an `hl.struct` or field of type + `tstruct`. Resolves (hail#13045) and (Hail#13046). +- (hail#12995) Fixed bug causing poor performance and memory leaks for `MatrixTable.annotate_rows` + aggregations. + ## Version 0.2.119 Released 2023-06-28 From d04c9b1e6a2f4b0a31e2245064faa713c813bd04 Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 27 Jul 2023 20:01:45 -0400 Subject: [PATCH 038/180] [all] update versions (#13276) Co-authored-by: Daniel Goldstein --- auth/auth/auth.py | 2 +- auth/auth/flow.py | 3 +- auth/pinned-requirements.txt | 6 +- batch/batch/front_end/query/operators.py | 5 +- batch/pinned-requirements.txt | 12 +- build.yaml | 1 + ci/pinned-requirements.txt | 12 +- gear/pinned-requirements.txt | 22 +- hail/python/dev/pinned-requirements.txt | 205 +++++++++--------- hail/python/hail/docs/overview/table.rst | 1 - hail/python/hailtop/aiocloud/aioaws/fs.py | 4 +- .../aiocloud/aioazure/client/graph_client.py | 4 +- hail/python/hailtop/aiocloud/aioazure/fs.py | 4 +- .../aiogoogle/client/storage_client.py | 4 +- hail/python/hailtop/aiotools/local_fs.py | 4 +- hail/python/hailtop/batch/backend.py | 4 +- hail/python/hailtop/hailctl/auth/login.py | 12 +- hail/python/hailtop/hailctl/describe.py | 2 +- hail/python/hailtop/pinned-requirements.txt | 40 ++-- hail/python/pinned-requirements.txt | 52 ++--- web_common/pinned-requirements.txt | 6 +- 21 files changed, 209 insertions(+), 196 deletions(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index a07229d7f32..dd4f79279c6 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -211,7 +211,7 @@ async def creating_account(request, userdata): page_context = {'username': user['username'], 'state': user['state'], 'login_id': user['login_id']} - if user['state'] == 'deleting' or user['state'] == 'deleted': + if user['state'] in ('deleting', 'deleted'): return await render_template('auth', request, userdata, 'account-error.html', page_context) if user['state'] == 'active': diff --git a/auth/auth/flow.py b/auth/auth/flow.py index bfaeb3fad8a..6f09ef18a20 100644 --- a/auth/auth/flow.py +++ b/auth/auth/flow.py @@ -1,6 +1,7 @@ import abc import json import urllib.parse +from typing import ClassVar, List import aiohttp.web import google.auth.transport.requests @@ -36,7 +37,7 @@ def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> Flo class GoogleFlow(Flow): - scopes = [ + scopes: ClassVar[List[str]] = [ 'https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email', 'openid', diff --git a/auth/pinned-requirements.txt b/auth/pinned-requirements.txt index 6a5c7c6e965..2cfa1041603 100644 --- a/auth/pinned-requirements.txt +++ b/auth/pinned-requirements.txt @@ -9,20 +9,20 @@ cachetools==5.3.1 # -c hail/auth/../gear/pinned-requirements.txt # -c hail/auth/../hail/python/pinned-requirements.txt # google-auth -certifi==2023.5.7 +certifi==2023.7.22 # via # -c hail/auth/../gear/pinned-requirements.txt # -c hail/auth/../hail/python/dev/pinned-requirements.txt # -c hail/auth/../hail/python/pinned-requirements.txt # requests -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # -c hail/auth/../gear/pinned-requirements.txt # -c hail/auth/../hail/python/dev/pinned-requirements.txt # -c hail/auth/../hail/python/pinned-requirements.txt # -c hail/auth/../web_common/pinned-requirements.txt # requests -google-auth==2.19.1 +google-auth==2.22.0 # via # -c hail/auth/../gear/pinned-requirements.txt # -c hail/auth/../hail/python/pinned-requirements.txt diff --git a/batch/batch/front_end/query/operators.py b/batch/batch/front_end/query/operators.py index d5d008bca2d..fb49d38a590 100644 --- a/batch/batch/front_end/query/operators.py +++ b/batch/batch/front_end/query/operators.py @@ -1,4 +1,5 @@ import abc +from typing import ClassVar, Set from ...exceptions import QueryError @@ -10,11 +11,11 @@ def to_sql(self) -> str: class ComparisonOperator(Operator, abc.ABC): - symbols = {'>=', '>', '<', '<=', '==', '=', '!='} + symbols: ClassVar[Set[str]] = {'>=', '>', '<', '<=', '==', '=', '!='} class MatchOperator(Operator, abc.ABC): - symbols = {'=', '!=', '!~', '=~'} + symbols: ClassVar[Set[str]] = {'=', '!=', '!~', '=~'} class PartialMatchOperator(MatchOperator, abc.ABC): diff --git a/batch/pinned-requirements.txt b/batch/pinned-requirements.txt index bcf931834a2..b9e0081303b 100644 --- a/batch/pinned-requirements.txt +++ b/batch/pinned-requirements.txt @@ -6,7 +6,7 @@ # aiodocker==0.21.0 # via -r hail/batch/requirements.txt -aiohttp==3.8.4 +aiohttp==3.8.5 # via # -c hail/batch/../gear/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt @@ -34,7 +34,7 @@ attrs==23.1.0 # -c hail/batch/../hail/python/pinned-requirements.txt # -c hail/batch/../web_common/pinned-requirements.txt # aiohttp -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # -c hail/batch/../gear/pinned-requirements.txt # -c hail/batch/../hail/python/dev/pinned-requirements.txt @@ -43,7 +43,7 @@ charset-normalizer==3.1.0 # aiohttp dictdiffer==0.9.0 # via -r hail/batch/requirements.txt -frozenlist==1.3.3 +frozenlist==1.4.0 # via # -c hail/batch/../gear/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt @@ -64,7 +64,7 @@ multidict==6.0.4 # -c hail/batch/../web_common/pinned-requirements.txt # aiohttp # yarl -numpy==1.24.3 +numpy==1.24.4 # via # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt @@ -74,7 +74,7 @@ packaging==23.1 # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt # plotly -pandas==2.0.2 +pandas==2.0.3 # via # -c hail/batch/../hail/python/pinned-requirements.txt # -r hail/batch/requirements.txt @@ -103,7 +103,7 @@ tenacity==8.2.2 # via # -c hail/batch/../hail/python/pinned-requirements.txt # plotly -typing-extensions==4.6.3 +typing-extensions==4.7.1 # via # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt diff --git a/build.yaml b/build.yaml index 6fbbb5c7d18..c74e5f5b66a 100644 --- a/build.yaml +++ b/build.yaml @@ -1423,6 +1423,7 @@ steps: --doctest-glob='*.rst' \ --ignore=$HAIL_LOCATION/docs/conf.py \ --ignore=$HAIL_LOCATION/docs/doctest_write_data.py \ + --rootdir $HAIL_LOCATION \ $HAIL_LOCATION/docs inputs: - from: /repo/hail/python/hail/docs diff --git a/ci/pinned-requirements.txt b/ci/pinned-requirements.txt index d0bd1e30a48..25812040c48 100644 --- a/ci/pinned-requirements.txt +++ b/ci/pinned-requirements.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=hail/ci/pinned-requirements.txt hail/ci/requirements.txt # -certifi==2023.5.7 +certifi==2023.7.22 # via # -c hail/ci/../gear/pinned-requirements.txt # -c hail/ci/../hail/python/dev/pinned-requirements.txt @@ -15,19 +15,19 @@ cffi==1.15.1 # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt # cryptography -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # -c hail/ci/../gear/pinned-requirements.txt # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt # -c hail/ci/../web_common/pinned-requirements.txt # requests -click==8.1.3 +click==8.1.6 # via # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt # zulip -cryptography==41.0.1 +cryptography==41.0.2 # via # -c hail/ci/../hail/python/pinned-requirements.txt # pyjwt @@ -49,7 +49,7 @@ pycparser==2.21 # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt # cffi -pyjwt[crypto]==2.7.0 +pyjwt[crypto]==2.8.0 # via # -c hail/ci/../hail/python/pinned-requirements.txt # gidgethub @@ -60,7 +60,7 @@ requests[security]==2.31.0 # -c hail/ci/../hail/python/pinned-requirements.txt # matrix-client # zulip -typing-extensions==4.6.3 +typing-extensions==4.7.1 # via # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt diff --git a/gear/pinned-requirements.txt b/gear/pinned-requirements.txt index 0aa15ca2af8..58589a13ad7 100644 --- a/gear/pinned-requirements.txt +++ b/gear/pinned-requirements.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=hail/gear/pinned-requirements.txt hail/gear/requirements.txt # -aiohttp==3.8.4 +aiohttp==3.8.5 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt @@ -35,34 +35,34 @@ cachetools==5.3.1 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # google-auth -certifi==2023.5.7 +certifi==2023.7.22 # via # -c hail/gear/../hail/python/dev/pinned-requirements.txt # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # kubernetes-asyncio # requests -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # -c hail/gear/../hail/python/dev/pinned-requirements.txt # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # requests -frozenlist==1.3.3 +frozenlist==1.4.0 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # aiosignal -google-api-core==2.11.0 +google-api-core==2.11.1 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # google-api-python-client -google-api-python-client==2.88.0 +google-api-python-client==2.95.0 # via google-cloud-profiler -google-auth==2.19.1 +google-auth==2.22.0 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt @@ -100,14 +100,14 @@ multidict==6.0.4 # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # yarl -orjson==3.9.1 +orjson==3.9.2 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # -r hail/gear/requirements.txt prometheus-async==19.2.0 # via -r hail/gear/requirements.txt -prometheus-client==0.17.0 +prometheus-client==0.17.1 # via # -c hail/gear/../hail/python/dev/pinned-requirements.txt # -r hail/gear/requirements.txt @@ -129,7 +129,7 @@ pyasn1-modules==0.3.0 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # google-auth -pymysql==1.0.3 +pymysql==1.1.0 # via # -r hail/gear/requirements.txt # aiomysql @@ -143,7 +143,7 @@ python-dateutil==2.8.2 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # kubernetes-asyncio -pyyaml==6.0 +pyyaml==6.0.1 # via # -c hail/gear/../hail/python/dev/pinned-requirements.txt # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt diff --git a/hail/python/dev/pinned-requirements.txt b/hail/python/dev/pinned-requirements.txt index 7c61adb7c43..23bad8ad78a 100644 --- a/hail/python/dev/pinned-requirements.txt +++ b/hail/python/dev/pinned-requirements.txt @@ -6,28 +6,30 @@ # alabaster==0.7.13 # via sphinx -anyio==3.7.0 +anyio==3.7.1 # via jupyter-server argon2-cffi==21.3.0 - # via - # jupyter-server - # nbclassic - # notebook + # via jupyter-server argon2-cffi-bindings==21.2.0 # via argon2-cffi arrow==1.2.3 # via isoduration -astroid==2.15.5 +astroid==2.15.6 # via pylint asttokens==2.2.1 # via stack-data +async-lru==2.0.3 + # via jupyterlab attrs==23.1.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt # curlylint # jsonschema + # referencing babel==2.12.1 - # via sphinx + # via + # jupyterlab-server + # sphinx backcall==0.2.0 # via ipython beautifulsoup4==4.12.2 @@ -36,7 +38,7 @@ black==22.12.0 # via -r hail/hail/python/dev/requirements.txt bleach==6.0.0 # via nbconvert -certifi==2023.5.7 +certifi==2023.7.22 # via # -c hail/hail/python/dev/../pinned-requirements.txt # requests @@ -44,11 +46,11 @@ cffi==1.15.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt # argon2-cffi-bindings -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt # requests -click==8.1.3 +click==8.1.6 # via # -c hail/hail/python/dev/../pinned-requirements.txt # -r hail/hail/python/dev/requirements.txt @@ -56,7 +58,7 @@ click==8.1.3 # curlylint comm==0.1.3 # via ipykernel -contourpy==1.0.7 +contourpy==1.1.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt # matplotlib @@ -72,7 +74,7 @@ decorator==4.4.2 # ipython defusedxml==0.7.1 # via nbconvert -dill==0.3.6 +dill==0.3.7 # via # -c hail/hail/python/dev/../pinned-requirements.txt # pylint @@ -81,17 +83,17 @@ docutils==0.18.1 # nbsphinx # sphinx # sphinx-rtd-theme -exceptiongroup==1.1.1 +exceptiongroup==1.1.2 # via # anyio # pytest -execnet==1.9.0 +execnet==2.0.2 # via pytest-xdist executing==1.2.0 # via stack-data -fastjsonschema==2.17.1 +fastjsonschema==2.18.0 # via nbformat -fonttools==4.40.0 +fonttools==4.41.1 # via matplotlib fqdn==1.5.1 # via jsonschema @@ -105,24 +107,29 @@ idna==3.4 # requests imagesize==1.4.1 # via sphinx -importlib-metadata==6.6.0 +importlib-metadata==6.8.0 # via # jupyter-client + # jupyter-lsp + # jupyterlab + # jupyterlab-server # nbconvert # sphinx -importlib-resources==5.12.0 +importlib-resources==6.0.0 # via # jsonschema + # jsonschema-specifications + # jupyterlab # matplotlib + # notebook iniconfig==2.0.0 # via pytest -ipykernel==6.23.2 +ipykernel==6.25.0 # via # ipywidgets # jupyter # jupyter-console - # nbclassic - # notebook + # jupyterlab # qtconsole ipython==8.12.2 # via @@ -130,11 +137,8 @@ ipython==8.12.2 # ipywidgets # jupyter-console ipython-genutils==0.2.0 - # via - # nbclassic - # notebook - # qtconsole -ipywidgets==8.0.6 + # via qtconsole +ipywidgets==8.0.7 # via jupyter isoduration==20.11.0 # via jsonschema @@ -146,53 +150,66 @@ jinja2==3.1.2 # via # -c hail/hail/python/dev/../pinned-requirements.txt # jupyter-server - # nbclassic + # jupyterlab + # jupyterlab-server # nbconvert # nbsphinx - # notebook # sphinx -jsonpointer==2.3 +json5==0.9.14 + # via jupyterlab-server +jsonpointer==2.4 # via jsonschema -jsonschema[format-nongpl]==4.17.3 +jsonschema[format-nongpl]==4.18.4 # via # jupyter-events + # jupyterlab-server # nbformat +jsonschema-specifications==2023.7.1 + # via jsonschema jupyter==1.0.0 # via -r hail/hail/python/dev/requirements.txt -jupyter-client==8.2.0 +jupyter-client==8.3.0 # via # ipykernel # jupyter-console # jupyter-server - # nbclassic # nbclient - # notebook # qtconsole jupyter-console==6.6.3 # via jupyter -jupyter-core==5.3.0 +jupyter-core==5.3.1 # via # ipykernel # jupyter-client # jupyter-console # jupyter-server - # nbclassic + # jupyterlab # nbclient # nbconvert # nbformat - # notebook # qtconsole jupyter-events==0.6.3 # via jupyter-server -jupyter-server==2.6.0 +jupyter-lsp==2.2.0 + # via jupyterlab +jupyter-server==2.7.0 # via - # nbclassic + # jupyter-lsp + # jupyterlab + # jupyterlab-server + # notebook # notebook-shim jupyter-server-terminals==0.4.4 # via jupyter-server +jupyterlab==4.0.3 + # via notebook jupyterlab-pygments==0.2.2 # via nbconvert -jupyterlab-widgets==3.0.7 +jupyterlab-server==2.24.0 + # via + # jupyterlab + # notebook +jupyterlab-widgets==3.0.8 # via ipywidgets kiwisolver==1.4.4 # via matplotlib @@ -203,7 +220,7 @@ markupsafe==2.1.3 # -c hail/hail/python/dev/../pinned-requirements.txt # jinja2 # nbconvert -matplotlib==3.7.1 +matplotlib==3.7.2 # via -r hail/hail/python/dev/requirements.txt matplotlib-inline==0.1.6 # via @@ -211,7 +228,7 @@ matplotlib-inline==0.1.6 # ipython mccabe==0.7.0 # via pylint -mistune==2.0.5 +mistune==3.0.1 # via nbconvert mypy==0.990 # via -r hail/hail/python/dev/requirements.txt @@ -219,38 +236,32 @@ mypy-extensions==1.0.0 # via # black # mypy -nbclassic==1.0.0 - # via notebook nbclient==0.8.0 # via nbconvert -nbconvert==7.4.0 +nbconvert==7.7.3 # via # jupyter # jupyter-server - # nbclassic # nbsphinx - # notebook -nbformat==5.9.0 +nbformat==5.9.1 # via # jupyter-server - # nbclassic # nbclient # nbconvert # nbsphinx - # notebook nbsphinx==0.9.2 # via -r hail/hail/python/dev/requirements.txt nest-asyncio==1.5.6 # via # -c hail/hail/python/dev/../pinned-requirements.txt # ipykernel - # nbclassic - # notebook -notebook==6.5.4 +notebook==7.0.0 # via jupyter notebook-shim==0.2.3 - # via nbclassic -numpy==1.24.3 + # via + # jupyterlab + # notebook +numpy==1.24.4 # via # -c hail/hail/python/dev/../pinned-requirements.txt # contourpy @@ -262,6 +273,8 @@ packaging==23.1 # -c hail/hail/python/dev/../pinned-requirements.txt # ipykernel # jupyter-server + # jupyterlab + # jupyterlab-server # matplotlib # nbconvert # pytest @@ -282,25 +295,22 @@ pexpect==4.8.0 # via ipython pickleshare==0.7.5 # via ipython -pillow==9.5.0 +pillow==10.0.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt # matplotlib pkgutil-resolve-name==1.3.10 # via jsonschema -platformdirs==3.5.3 +platformdirs==3.9.1 # via # black # jupyter-core # pylint -pluggy==1.0.0 +pluggy==1.2.0 # via pytest -prometheus-client==0.17.0 - # via - # jupyter-server - # nbclassic - # notebook -prompt-toolkit==3.0.38 +prometheus-client==0.17.1 + # via jupyter-server +prompt-toolkit==3.0.39 # via # ipython # jupyter-console @@ -326,13 +336,11 @@ pygments==2.15.1 # nbconvert # qtconsole # sphinx -pylint==2.17.4 +pylint==2.17.5 # via -r hail/hail/python/dev/requirements.txt pyparsing==3.0.9 # via matplotlib -pyrsistent==0.19.3 - # via jsonschema -pytest==7.3.2 +pytest==7.4.0 # via # -r hail/hail/python/dev/requirements.txt # pytest-asyncio @@ -342,7 +350,7 @@ pytest==7.3.2 # pytest-metadata # pytest-timeout # pytest-xdist -pytest-asyncio==0.21.0 +pytest-asyncio==0.21.1 # via -r hail/hail/python/dev/requirements.txt pytest-forked==1.6.0 # via pytest-xdist @@ -371,7 +379,7 @@ pytz==2023.3 # via # -c hail/hail/python/dev/../pinned-requirements.txt # babel -pyyaml==6.0 +pyyaml==6.0.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt # jupyter-events @@ -381,16 +389,19 @@ pyzmq==25.1.0 # jupyter-client # jupyter-console # jupyter-server - # nbclassic - # notebook # qtconsole qtconsole==5.4.3 # via jupyter qtpy==2.3.1 # via qtconsole +referencing==0.30.0 + # via + # jsonschema + # jsonschema-specifications requests==2.31.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt + # jupyterlab-server # sphinx rfc3339-validator==0.1.4 # via @@ -400,13 +411,14 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -ruff==0.0.272 +rpds-py==0.9.2 + # via + # jsonschema + # referencing +ruff==0.0.280 # via -r hail/hail/python/dev/requirements.txt send2trash==1.8.2 - # via - # jupyter-server - # nbclassic - # notebook + # via jupyter-server six==1.16.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt @@ -442,7 +454,7 @@ sphinxcontrib-jquery==4.1 # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx -sphinxcontrib-katex==0.9.5 +sphinxcontrib-katex==0.9.7 # via -r hail/hail/python/dev/requirements.txt sphinxcontrib-qthelp==1.0.3 # via sphinx @@ -454,8 +466,6 @@ terminado==0.17.1 # via # jupyter-server # jupyter-server-terminals - # nbclassic - # notebook tinycss2==1.2.1 # via nbconvert toml==0.10.2 @@ -463,6 +473,7 @@ toml==0.10.2 tomli==2.0.1 # via # black + # jupyterlab # mypy # pylint # pytest @@ -474,7 +485,7 @@ tornado==6.3.2 # ipykernel # jupyter-client # jupyter-server - # nbclassic + # jupyterlab # notebook # terminado traitlets==5.9.0 @@ -488,47 +499,47 @@ traitlets==5.9.0 # jupyter-core # jupyter-events # jupyter-server + # jupyterlab # matplotlib-inline - # nbclassic # nbclient # nbconvert # nbformat # nbsphinx - # notebook # qtconsole types-chardet==5.0.4.6 # via -r hail/hail/python/dev/requirements.txt -types-decorator==5.1.8.3 +types-decorator==5.1.8.4 # via -r hail/hail/python/dev/requirements.txt -types-deprecated==1.2.9.2 +types-deprecated==1.2.9.3 # via -r hail/hail/python/dev/requirements.txt -types-pymysql==1.0.19.7 +types-pymysql==1.1.0.1 # via -r hail/hail/python/dev/requirements.txt -types-python-dateutil==2.8.19.13 +types-python-dateutil==2.8.19.14 # via -r hail/hail/python/dev/requirements.txt -types-pyyaml==6.0.12.10 +types-pyyaml==6.0.12.11 # via -r hail/hail/python/dev/requirements.txt -types-requests==2.31.0.1 +types-requests==2.31.0.2 # via -r hail/hail/python/dev/requirements.txt -types-setuptools==67.8.0.0 +types-setuptools==68.0.0.3 # via -r hail/hail/python/dev/requirements.txt -types-six==1.16.21.8 +types-six==1.16.21.9 # via -r hail/hail/python/dev/requirements.txt -types-tabulate==0.9.0.2 +types-tabulate==0.9.0.3 # via -r hail/hail/python/dev/requirements.txt -types-urllib3==1.26.25.13 +types-urllib3==1.26.25.14 # via # -r hail/hail/python/dev/requirements.txt # types-requests -typing-extensions==4.6.3 +typing-extensions==4.7.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt # astroid + # async-lru # black # ipython # mypy # pylint -uri-template==1.2.0 +uri-template==1.3.0 # via jsonschema urllib3==1.26.16 # via @@ -542,15 +553,15 @@ webencodings==0.5.1 # via # bleach # tinycss2 -websocket-client==1.5.3 +websocket-client==1.6.1 # via jupyter-server -widgetsnbextension==4.0.7 +widgetsnbextension==4.0.8 # via ipywidgets wrapt==1.15.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt # astroid -zipp==3.15.0 +zipp==3.16.2 # via # importlib-metadata # importlib-resources diff --git a/hail/python/hail/docs/overview/table.rst b/hail/python/hail/docs/overview/table.rst index 563faa10b58..1281ea252a3 100644 --- a/hail/python/hail/docs/overview/table.rst +++ b/hail/python/hail/docs/overview/table.rst @@ -242,4 +242,3 @@ table and their types. The types themselves can be accessed using the fields ``ht.row.dtype`` and ``ht.globals.dtype``. The row fields that are part of the key can be accessed with :attr:`.Table.key`. The :meth:`.Table.count` method returns the number of rows. - diff --git a/hail/python/hailtop/aiocloud/aioaws/fs.py b/hail/python/hailtop/aiocloud/aioaws/fs.py index a9a92ecc027..3d8f063a747 100644 --- a/hail/python/hailtop/aiocloud/aioaws/fs.py +++ b/hail/python/hailtop/aiocloud/aioaws/fs.py @@ -1,5 +1,5 @@ from typing import (Any, AsyncIterator, BinaryIO, cast, AsyncContextManager, Dict, List, Optional, - Set, Tuple, Type) + Set, Tuple, Type, ClassVar) from types import TracebackType import sys from concurrent.futures import ThreadPoolExecutor @@ -297,7 +297,7 @@ def __str__(self) -> str: class S3AsyncFS(AsyncFS): - schemes: Set[str] = {'s3'} + schemes: ClassVar[Set[str]] = {'s3'} def __init__(self, thread_pool: Optional[ThreadPoolExecutor] = None, max_workers: Optional[int] = None, *, max_pool_connections: int = 10): if not thread_pool: diff --git a/hail/python/hailtop/aiocloud/aioazure/client/graph_client.py b/hail/python/hailtop/aiocloud/aioazure/client/graph_client.py index 00e0519bc74..982b3cbcc92 100644 --- a/hail/python/hailtop/aiocloud/aioazure/client/graph_client.py +++ b/hail/python/hailtop/aiocloud/aioazure/client/graph_client.py @@ -1,11 +1,11 @@ -from typing import Optional +from typing import Optional, ClassVar, List from ..session import AzureSession from .base_client import AzureBaseClient class AzureGraphClient(AzureBaseClient): - required_scopes = ['https://graph.microsoft.com/.default'] + required_scopes: ClassVar[List[str]] = ['https://graph.microsoft.com/.default'] def __init__(self, session: Optional[AzureSession] = None, **kwargs): if 'scopes' in kwargs: diff --git a/hail/python/hailtop/aiocloud/aioazure/fs.py b/hail/python/hailtop/aiocloud/aioazure/fs.py index 5361f3e980e..0263d096cc9 100644 --- a/hail/python/hailtop/aiocloud/aioazure/fs.py +++ b/hail/python/hailtop/aiocloud/aioazure/fs.py @@ -1,4 +1,4 @@ -from typing import Any, AsyncContextManager, AsyncIterator, Dict, List, Optional, Set, Tuple, Type, Union +from typing import Any, AsyncContextManager, AsyncIterator, Dict, List, Optional, Set, Tuple, Type, Union, ClassVar from types import TracebackType import abc @@ -348,7 +348,7 @@ async def wrapped(self: 'AzureAsyncFS', url, *args, **kwargs): class AzureAsyncFS(AsyncFS): - schemes: Set[str] = {'hail-az', 'https'} + schemes: ClassVar[Set[str]] = {'hail-az', 'https'} PATH_REGEX = re.compile('/(?P[^/]+)(?P.*)') def __init__(self, *, credential_file: Optional[str] = None, credentials: Optional[AzureCredentials] = None): diff --git a/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py b/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py index 7f6b2a285f5..ee217f11911 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py @@ -1,6 +1,6 @@ import os from typing import (Tuple, Any, Set, Optional, MutableMapping, Dict, AsyncIterator, cast, Type, - List, Coroutine) + List, Coroutine, ClassVar) from types import TracebackType from multidict import CIMultiDictProxy # pylint: disable=unused-import import sys @@ -584,7 +584,7 @@ def __str__(self) -> str: class GoogleStorageAsyncFS(AsyncFS): - schemes: Set[str] = {'gs'} + schemes: ClassVar[Set[str]] = {'gs'} def __init__(self, *, storage_client: Optional[GoogleStorageClient] = None, diff --git a/hail/python/hailtop/aiotools/local_fs.py b/hail/python/hailtop/aiotools/local_fs.py index a0fb11122b7..52655c49c02 100644 --- a/hail/python/hailtop/aiotools/local_fs.py +++ b/hail/python/hailtop/aiotools/local_fs.py @@ -1,4 +1,4 @@ -from typing import Any, Optional, Type, BinaryIO, cast, Set, AsyncIterator, Callable, Dict, List +from typing import Any, Optional, Type, BinaryIO, cast, Set, AsyncIterator, Callable, Dict, List, ClassVar from types import TracebackType import os import os.path @@ -217,7 +217,7 @@ def __next__(self): class LocalAsyncFS(AsyncFS): - schemes: Set[str] = {'file'} + schemes: ClassVar[Set[str]] = {'file'} def __init__(self, thread_pool: Optional[ThreadPoolExecutor] = None, max_workers: Optional[int] = None): if not thread_pool: diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index c95e7af53da..371f8129e67 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -1,4 +1,4 @@ -from typing import Optional, Dict, Any, TypeVar, Generic, List, Union +from typing import Optional, Dict, Any, TypeVar, Generic, List, Union, ClassVar import sys import abc import asyncio @@ -380,7 +380,7 @@ def _close(self): class ServiceBackend(Backend[bc.Batch]): - ANY_REGION = ['any_region'] + ANY_REGION: ClassVar[List[str]] = ['any_region'] """Backend that executes batches on Hail's Batch Service on Google Cloud. diff --git a/hail/python/hailtop/hailctl/auth/login.py b/hail/python/hailtop/hailctl/auth/login.py index 4b9d5d0f284..ece369f3beb 100644 --- a/hail/python/hailtop/hailctl/auth/login.py +++ b/hail/python/hailtop/hailctl/auth/login.py @@ -46,10 +46,10 @@ async def auth_flow(deploy_config, default_ns, session): runner, port = await start_server() async with session.get(deploy_config.url('auth', '/api/v1alpha/login'), params={'callback_port': port}) as resp: - resp = await resp.json() + json_resp = await resp.json() - flow = resp['flow'] - state = flow['state'] + flow = json_resp['flow'] + state = json_resp['state'] authorization_url = flow['authorization_url'] print( @@ -75,9 +75,9 @@ async def auth_flow(deploy_config, default_ns, session): 'flow': json.dumps(flow), }, ) as resp: - resp = await resp.json() - token = resp['token'] - username = resp['username'] + json_resp = await resp.json() + token = json_resp['token'] + username = json_resp['username'] tokens = get_tokens() tokens[default_ns] = token diff --git a/hail/python/hailtop/hailctl/describe.py b/hail/python/hailtop/hailctl/describe.py index 5f1c963c2da..948b614db0a 100644 --- a/hail/python/hailtop/hailctl/describe.py +++ b/hail/python/hailtop/hailctl/describe.py @@ -120,7 +120,7 @@ async def async_describe( j = orjson.loads(decompress(await fs.read(path.join(file, 'metadata.json.gz')), 16 + MAX_WBITS)) # Get the file schema - file_schema = parse_schema(j[[k for k in j.keys() if k.endswith('type')][0]]) + file_schema = parse_schema(j[next(k for k in j.keys() if k.endswith('type'))]) # Print file information print(SECTION_SEPARATOR) diff --git a/hail/python/hailtop/pinned-requirements.txt b/hail/python/hailtop/pinned-requirements.txt index b05e101f15a..cb3525377c0 100644 --- a/hail/python/hailtop/pinned-requirements.txt +++ b/hail/python/hailtop/pinned-requirements.txt @@ -6,7 +6,7 @@ # aiodns==2.0.0 # via -r hail/hail/python/hailtop/requirements.txt -aiohttp==3.8.4 +aiohttp==3.8.5 # via -r hail/hail/python/hailtop/requirements.txt aiosignal==1.3.1 # via aiohttp @@ -16,7 +16,7 @@ attrs==23.1.0 # via aiohttp azure-common==1.1.28 # via azure-mgmt-storage -azure-core==1.27.0 +azure-core==1.28.0 # via # azure-identity # azure-mgmt-core @@ -28,18 +28,18 @@ azure-mgmt-core==1.4.0 # via azure-mgmt-storage azure-mgmt-storage==20.1.0 # via -r hail/hail/python/hailtop/requirements.txt -azure-storage-blob==12.16.0 +azure-storage-blob==12.17.0 # via -r hail/hail/python/hailtop/requirements.txt -boto3==1.26.152 +boto3==1.28.11 # via -r hail/hail/python/hailtop/requirements.txt -botocore==1.29.152 +botocore==1.31.11 # via # -r hail/hail/python/hailtop/requirements.txt # boto3 # s3transfer cachetools==5.3.1 # via google-auth -certifi==2023.5.7 +certifi==2023.7.22 # via # msrest # requests @@ -47,40 +47,40 @@ cffi==1.15.1 # via # cryptography # pycares -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # aiohttp # requests -click==8.1.3 +click==8.1.6 # via typer commonmark==0.9.1 # via rich -cryptography==41.0.1 +cryptography==41.0.2 # via # azure-identity # azure-storage-blob # msal # pyjwt -dill==0.3.6 +dill==0.3.7 # via -r hail/hail/python/hailtop/requirements.txt -frozenlist==1.3.3 +frozenlist==1.4.0 # via # -r hail/hail/python/hailtop/requirements.txt # aiohttp # aiosignal -google-api-core==2.11.0 +google-api-core==2.11.1 # via # google-cloud-core # google-cloud-storage -google-auth==2.19.1 +google-auth==2.22.0 # via # -r hail/hail/python/hailtop/requirements.txt # google-api-core # google-cloud-core # google-cloud-storage -google-cloud-core==2.3.2 +google-cloud-core==2.3.3 # via google-cloud-storage -google-cloud-storage==2.9.0 +google-cloud-storage==2.10.0 # via -r hail/hail/python/hailtop/requirements.txt google-crc32c==1.5.0 # via google-resumable-media @@ -106,7 +106,7 @@ jmespath==1.0.1 # botocore jproperties==2.1.1 # via -r hail/hail/python/hailtop/requirements.txt -msal==1.22.0 +msal==1.23.0 # via # azure-identity # msal-extensions @@ -122,7 +122,7 @@ nest-asyncio==1.5.6 # via -r hail/hail/python/hailtop/requirements.txt oauthlib==3.2.2 # via requests-oauthlib -orjson==3.9.1 +orjson==3.9.2 # via -r hail/hail/python/hailtop/requirements.txt portalocker==2.7.0 # via msal-extensions @@ -143,13 +143,13 @@ pycparser==2.21 # via cffi pygments==2.15.1 # via rich -pyjwt[crypto]==2.7.0 +pyjwt[crypto]==2.8.0 # via msal python-dateutil==2.8.2 # via botocore python-json-logger==2.0.7 # via -r hail/hail/python/hailtop/requirements.txt -pyyaml==6.0 +pyyaml==6.0.1 # via -r hail/hail/python/hailtop/requirements.txt requests==2.31.0 # via @@ -181,7 +181,7 @@ tabulate==0.9.0 # via -r hail/hail/python/hailtop/requirements.txt typer==0.9.0 # via -r hail/hail/python/hailtop/requirements.txt -typing-extensions==4.6.3 +typing-extensions==4.7.1 # via # azure-core # azure-storage-blob diff --git a/hail/python/pinned-requirements.txt b/hail/python/pinned-requirements.txt index 423f98b89a5..cce6e011240 100644 --- a/hail/python/pinned-requirements.txt +++ b/hail/python/pinned-requirements.txt @@ -8,7 +8,7 @@ aiodns==2.0.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -aiohttp==3.8.4 +aiohttp==3.8.5 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -26,13 +26,13 @@ attrs==23.1.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # aiohttp -avro==1.11.1 +avro==1.11.2 # via -r hail/hail/python/requirements.txt azure-common==1.1.28 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-mgmt-storage -azure-core==1.27.0 +azure-core==1.28.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-identity @@ -51,17 +51,17 @@ azure-mgmt-storage==20.1.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -azure-storage-blob==12.16.0 +azure-storage-blob==12.17.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt bokeh==3.1.1 # via -r hail/hail/python/requirements.txt -boto3==1.26.152 +boto3==1.28.11 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -botocore==1.29.152 +botocore==1.31.11 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -71,7 +71,7 @@ cachetools==5.3.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # google-auth -certifi==2023.5.7 +certifi==2023.7.22 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # msrest @@ -81,12 +81,12 @@ cffi==1.15.1 # -c hail/hail/python/hailtop/pinned-requirements.txt # cryptography # pycares -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # aiohttp # requests -click==8.1.3 +click==8.1.6 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # typer @@ -94,9 +94,9 @@ commonmark==0.9.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # rich -contourpy==1.0.7 +contourpy==1.1.0 # via bokeh -cryptography==41.0.1 +cryptography==41.0.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-identity @@ -107,35 +107,35 @@ decorator==4.4.2 # via -r hail/hail/python/requirements.txt deprecated==1.2.14 # via -r hail/hail/python/requirements.txt -dill==0.3.6 +dill==0.3.7 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt # -r hail/hail/python/requirements.txt -frozenlist==1.3.3 +frozenlist==1.4.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt # -r hail/hail/python/requirements.txt # aiohttp # aiosignal -google-api-core==2.11.0 +google-api-core==2.11.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # google-cloud-core # google-cloud-storage -google-auth==2.19.1 +google-auth==2.22.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt # google-api-core # google-cloud-core # google-cloud-storage -google-cloud-core==2.3.2 +google-cloud-core==2.3.3 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # google-cloud-storage -google-cloud-storage==2.9.0 +google-cloud-storage==2.10.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -184,7 +184,7 @@ jproperties==2.1.1 # -r hail/hail/python/hailtop/requirements.txt markupsafe==2.1.3 # via jinja2 -msal==1.22.0 +msal==1.23.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-identity @@ -206,7 +206,7 @@ nest-asyncio==1.5.6 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -numpy==1.24.3 +numpy==1.24.4 # via # -r hail/hail/python/requirements.txt # bokeh @@ -217,7 +217,7 @@ oauthlib==3.2.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # requests-oauthlib -orjson==3.9.1 +orjson==3.9.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -225,13 +225,13 @@ packaging==23.1 # via # bokeh # plotly -pandas==2.0.2 +pandas==2.0.3 # via # -r hail/hail/python/requirements.txt # bokeh parsimonious==0.10.0 # via -r hail/hail/python/requirements.txt -pillow==9.5.0 +pillow==10.0.0 # via bokeh plotly==5.15.0 # via -r hail/hail/python/requirements.txt @@ -269,7 +269,7 @@ pygments==2.15.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # rich -pyjwt[crypto]==2.7.0 +pyjwt[crypto]==2.8.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # msal @@ -286,7 +286,7 @@ python-json-logger==2.0.7 # -r hail/hail/python/hailtop/requirements.txt pytz==2023.3 # via pandas -pyyaml==6.0 +pyyaml==6.0.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -346,7 +346,7 @@ typer==0.9.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -typing-extensions==4.6.3 +typing-extensions==4.7.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-core @@ -368,7 +368,7 @@ uvloop==0.17.0 ; sys_platform != "win32" # -r hail/hail/python/hailtop/requirements.txt wrapt==1.15.0 # via deprecated -xyzservices==2023.5.0 +xyzservices==2023.7.0 # via bokeh yarl==1.9.2 # via diff --git a/web_common/pinned-requirements.txt b/web_common/pinned-requirements.txt index af504735032..6440ef1975a 100644 --- a/web_common/pinned-requirements.txt +++ b/web_common/pinned-requirements.txt @@ -4,7 +4,7 @@ # # pip-compile --output-file=hail/web_common/pinned-requirements.txt hail/web_common/requirements.txt # -aiohttp==3.8.4 +aiohttp==3.8.5 # via # -c hail/web_common/../gear/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt @@ -27,13 +27,13 @@ attrs==23.1.0 # -c hail/web_common/../hail/python/dev/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt # aiohttp -charset-normalizer==3.1.0 +charset-normalizer==3.2.0 # via # -c hail/web_common/../gear/pinned-requirements.txt # -c hail/web_common/../hail/python/dev/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt # aiohttp -frozenlist==1.3.3 +frozenlist==1.4.0 # via # -c hail/web_common/../gear/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt From 479f134a709e7b92d99d8c602821be1159e84e53 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 27 Jul 2023 22:26:57 -0400 Subject: [PATCH 039/180] [gear] Add typing to the transaction decorator (#13308) Adding this signature appeases `pyright` in my editor. Unfortunately, `pylint` still [gets confused](https://github.com/pylint-dev/pylint/issues/259) so I disabled this particular check. I made sure that `mypy` still errors when forgetting to provide a required parameter to a function call. --- auth/auth/auth.py | 4 ++-- batch/batch/batch.py | 2 +- batch/batch/driver/billing_manager.py | 4 ++-- batch/batch/driver/instance.py | 2 +- batch/batch/driver/main.py | 4 ++-- batch/batch/front_end/front_end.py | 20 ++++++++++---------- ci/bootstrap_create_accounts.py | 2 +- gear/gear/database.py | 15 +++++++++------ monitoring/monitoring/monitoring.py | 2 +- pylintrc | 5 ++++- 10 files changed, 33 insertions(+), 27 deletions(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index dd4f79279c6..9fbbeb46916 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -162,7 +162,7 @@ async def _insert(tx): ), ) - await _insert() # pylint: disable=no-value-for-parameter + await _insert() return True @@ -696,7 +696,7 @@ async def maybe_pop_token(tx): await tx.just_execute("DELETE FROM copy_paste_tokens WHERE id = %s;", copy_paste_token) return session - session = await maybe_pop_token() # pylint: disable=no-value-for-parameter + session = await maybe_pop_token() return json_response({'token': session['session_id'], 'username': session['username']}) diff --git a/batch/batch/batch.py b/batch/batch/batch.py index 137b9eec3aa..19b7f092b64 100644 --- a/batch/batch/batch.py +++ b/batch/batch/batch.py @@ -112,4 +112,4 @@ async def cancel(tx): await tx.just_execute('CALL cancel_batch(%s);', (batch_id,)) - await cancel() # pylint: disable=no-value-for-parameter + await cancel() diff --git a/batch/batch/driver/billing_manager.py b/batch/batch/driver/billing_manager.py index 123c735e431..578fd7a29fb 100644 --- a/batch/batch/driver/billing_manager.py +++ b/batch/batch/driver/billing_manager.py @@ -149,7 +149,7 @@ async def insert_or_update(tx): product_version_updates, ) - await insert_or_update() # pylint: disable=no-value-for-parameter + await insert_or_update() if resource_updates or product_version_updates: await self.refresh_resources() @@ -164,7 +164,7 @@ async def refresh(tx): self.product_versions.update(latest_product_versions) log.info('refreshed product versions') - await refresh() # pylint: disable=no-value-for-parameter + await refresh() async def refresh_product_versions_from_db(db: Database) -> Dict[str, str]: diff --git a/batch/batch/driver/instance.py b/batch/batch/driver/instance.py index eea0ec149f5..413aaac0e20 100644 --- a/batch/batch/driver/instance.py +++ b/batch/batch/driver/instance.py @@ -95,7 +95,7 @@ async def insert(tx): ), ) - await insert() # pylint: disable=no-value-for-parameter + await insert() return Instance( app, diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 3690028edad..7573f91ffcf 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -1076,7 +1076,7 @@ async def check(tx): if len(failures) > 0: raise ValueError(json.dumps(failures)) - await check() # pylint: disable=no-value-for-parameter + await check() async def check_resource_aggregation(db): @@ -1217,7 +1217,7 @@ async def check(tx): agg_billing_project_resources, ) - await check() # pylint: disable=no-value-for-parameter + await check() async def _cancel_batch(app, batch_id): diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index 91f05e36f40..4deddf2fa79 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -1170,7 +1170,7 @@ async def write_and_insert(tx): # must rollback. See https://github.com/hail-is/hail-production-issues/issues/9 await asyncio.gather(write_spec_to_cloud(), insert_jobs_into_db(tx)) - await write_and_insert() # pylint: disable=no-value-for-parameter + await write_and_insert() return web.Response() @@ -1330,7 +1330,7 @@ async def insert(tx): ) return id - return await insert() # pylint: disable=no-value-for-parameter + return await insert() @routes.post('/api/v1alpha/batches/{batch_id}/update-fast') @@ -1456,7 +1456,7 @@ async def update(tx: Transaction): return (update_id, update_start_job_id) - return await update() # pylint: disable=no-value-for-parameter + return await update() async def _get_batch(app, batch_id): @@ -2241,7 +2241,7 @@ async def insert(tx): (limit, billing_project), ) - await insert() # pylint: disable=no-value-for-parameter + await insert() @routes.post('/api/v1alpha/billing_limits/{billing_project}/edit') @@ -2478,7 +2478,7 @@ async def delete(tx): (billing_project, user), ) - await delete() # pylint: disable=no-value-for-parameter + await delete() @routes.post('/billing_projects/{billing_project}/users/{user}/remove') @@ -2548,7 +2548,7 @@ async def insert(tx): (billing_project, user, user), ) - await insert() # pylint: disable=no-value-for-parameter + await insert() @routes.post('/billing_projects/{billing_project}/users/add') @@ -2606,7 +2606,7 @@ async def insert(tx): (billing_project, billing_project), ) - await insert() # pylint: disable=no-value-for-parameter + await insert() @routes.post('/billing_projects/create') @@ -2667,7 +2667,7 @@ async def close_project(tx): "UPDATE billing_projects SET `status` = 'closed' WHERE name_cs = %s;", (billing_project,) ) - await close_project() # pylint: disable=no-value-for-parameter + await close_project() @routes.post('/billing_projects/{billing_project}/close') @@ -2712,7 +2712,7 @@ async def open_project(tx): await tx.execute_update("UPDATE billing_projects SET `status` = 'open' WHERE name_cs = %s;", (billing_project,)) - await open_project() # pylint: disable=no-value-for-parameter + await open_project() @routes.post('/billing_projects/{billing_project}/reopen') @@ -2758,7 +2758,7 @@ async def delete_project(tx): "UPDATE billing_projects SET `status` = 'deleted' WHERE name_cs = %s;", (billing_project,) ) - await delete_project() # pylint: disable=no-value-for-parameter + await delete_project() @routes.post('/api/v1alpha/billing_projects/{billing_project}/delete') diff --git a/ci/bootstrap_create_accounts.py b/ci/bootstrap_create_accounts.py index a6cae36a74b..049a9539aee 100644 --- a/ci/bootstrap_create_accounts.py +++ b/ci/bootstrap_create_accounts.py @@ -62,7 +62,7 @@ async def insert(tx): ), ) - return await insert() # pylint: disable=no-value-for-parameter + return await insert() async def main(): diff --git a/gear/gear/database.py b/gear/gear/database.py index 82d0ed59dc5..3b2da5f4e51 100644 --- a/gear/gear/database.py +++ b/gear/gear/database.py @@ -4,7 +4,7 @@ import os import ssl import traceback -from typing import Optional +from typing import Awaitable, Callable, Optional, TypeVar import aiomysql import kubernetes_asyncio.client @@ -59,13 +59,16 @@ async def wrapper(*args, **kwargs): return wrapper -def transaction(db, **transaction_kwargs): - def transformer(fun): +T = TypeVar("T") + + +def transaction(db: 'Database', read_only: bool = False): + def transformer(fun: Callable[['Transaction'], Awaitable[T]]) -> Callable[[], Awaitable[T]]: @functools.wraps(fun) @retry_transient_mysql_errors - async def wrapper(*args, **kwargs): - async with db.start(**transaction_kwargs) as tx: - return await fun(tx, *args, **kwargs) + async def wrapper(): + async with db.start(read_only=read_only) as tx: + return await fun(tx) return wrapper diff --git a/monitoring/monitoring/monitoring.py b/monitoring/monitoring/monitoring.py index cb9f1471a73..c69affcb67d 100644 --- a/monitoring/monitoring/monitoring.py +++ b/monitoring/monitoring/monitoring.py @@ -231,7 +231,7 @@ async def insert(tx): records, ) - await insert() # pylint: disable=no-value-for-parameter + await insert() log.info('updating billing information') now = datetime.datetime.now() diff --git a/pylintrc b/pylintrc index 575e2c3743c..e93bb0ac0b0 100644 --- a/pylintrc +++ b/pylintrc @@ -17,7 +17,10 @@ ignore=sql # C1801 Do not use len(SEQUENCE) as condition value # W0221 Parameters differ from overridden method -disable=C0111,W1203,W1202,C0111,R0913,W0622,W0212,W0621,R0914,W0603,R0902,R0801,C1801,W0221,line-too-long,too-few-public-methods,fixme,too-many-function-args,too-many-branches,too-many-lines,too-many-boolean-expressions,too-many-statements,too-many-nested-blocks,wrong-import-order,logging-not-lazy,unnecessary-lambda,unnecessary-lambda-assignment,too-many-public-methods,broad-except,too-many-return-statements,bare-except,invalid-name,unsubscriptable-object,consider-using-f-string,try-except-raise +# Reasons for disabling: +# no-value-for-parameter -- See bug in pylint https://github.com/pylint-dev/pylint/issues/259 and this is covered by mypy + +disable=C0111,W1203,W1202,C0111,R0913,W0622,W0212,W0621,R0914,W0603,R0902,R0801,C1801,W0221,line-too-long,too-few-public-methods,fixme,too-many-function-args,too-many-branches,too-many-lines,too-many-boolean-expressions,too-many-statements,too-many-nested-blocks,wrong-import-order,logging-not-lazy,unnecessary-lambda,unnecessary-lambda-assignment,too-many-public-methods,broad-except,too-many-return-statements,bare-except,invalid-name,unsubscriptable-object,consider-using-f-string,try-except-raise,no-value-for-parameter [FORMAT] # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 From 8d69b541f32bed97ab4937952f4f6210a514a9bc Mon Sep 17 00:00:00 2001 From: sjparsa <66189052+sjparsa@users.noreply.github.com> Date: Fri, 28 Jul 2023 09:21:43 -0400 Subject: [PATCH 040/180] update query on batch tmp config flag (#13258) The config flag batch/tmp_dir is now batch/remote_tmpdir Co-authored-by: Sophie Parsa --- hail/python/hail/docs/cloud/query_on_batch.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hail/python/hail/docs/cloud/query_on_batch.rst b/hail/python/hail/docs/cloud/query_on_batch.rst index 535d4eccf05..3153abf6a89 100644 --- a/hail/python/hail/docs/cloud/query_on_batch.rst +++ b/hail/python/hail/docs/cloud/query_on_batch.rst @@ -38,7 +38,7 @@ Getting Started .. code-block:: text - hailctl config set batch/tmp_dir gs://my-auto-delete-bucket/hail-query-temporaries + hailctl config set batch/remote_tmpdir gs://my-auto-delete-bucket/hail-query-temporaries 4. Specify a Hail Batch billing project (these are different from Google Cloud projects). Every new user has a trial billing project loaded with 10 USD. The name is available on the `Hail User From fbec6096d5af8a6e7966c239e49868179ba176dd Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Fri, 28 Jul 2023 12:25:39 -0400 Subject: [PATCH 041/180] [qob] restart docker after vep initialization (#13327) fix #12936 --- hail/python/hailtop/hailctl/dataproc/resources/vep-GRCh38.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hail/python/hailtop/hailctl/dataproc/resources/vep-GRCh38.sh b/hail/python/hailtop/hailctl/dataproc/resources/vep-GRCh38.sh index d86ed4d103e..991b4956e2a 100644 --- a/hail/python/hailtop/hailctl/dataproc/resources/vep-GRCh38.sh +++ b/hail/python/hailtop/hailctl/dataproc/resources/vep-GRCh38.sh @@ -56,3 +56,5 @@ docker run -i -v /vep_data/:/opt/vep/.vep/:ro ${VEP_DOCKER_IMAGE} \ /opt/vep/src/ensembl-vep/vep "\$@" EOF chmod +x /vep.sh + +sudo service docker restart From 5f6871668ba251e4f60ab292d253ba8f1d84a5c7 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 28 Jul 2023 15:56:37 -0400 Subject: [PATCH 042/180] [omnibus] all approved passing PRs including ones critical to get CI moving again (#13325) See each message below. --- [[query/vds] Fix local_to_global with missing fill](https://github.com/hail-is/hail/pull/13325/commits/7d84189ca1a1b9460f4e0c96821cd43b8b0068fa) There was a logic error in constructFromIndicesUnsafe, if a missing value was pushed, pushing a present value with the same index would not clear the missing bit. --- [[batch/test] Wait for job to be running in list_jobs_v2 test](https://github.com/hail-is/hail/pull/13325/commits/724da249255c06ea4ed1816704e4de51bd8f9b89) --- [[qob] halve the number of active tests](https://github.com/hail-is/hail/pull/13325/commits/c2638702325526b29bebd416fceeedea52d42245) --- [[batch] Turn off oms_agent in test and dev](https://github.com/hail-is/hail/pull/13325/commits/bbd65e4f66d41ef69c130091b0506087975c4851) --- --------- Co-authored-by: Chris Vittal Co-authored-by: Jackie Goldstein --- batch/sql/turn_off_oms_agent_test_dev.py | 20 +++++++++ batch/test/test_batch.py | 41 ++++++++----------- build.yaml | 7 +++- hail/python/hailtop/batch_client/aioclient.py | 21 ++++++---- hail/python/hailtop/batch_client/client.py | 3 ++ hail/python/test/hail/conftest.py | 1 + .../test/hail/vds/test_vds_functions.py | 7 +++- .../hail/types/physical/PCanonicalArray.scala | 1 + 8 files changed, 65 insertions(+), 36 deletions(-) create mode 100644 batch/sql/turn_off_oms_agent_test_dev.py diff --git a/batch/sql/turn_off_oms_agent_test_dev.py b/batch/sql/turn_off_oms_agent_test_dev.py new file mode 100644 index 00000000000..21be4914161 --- /dev/null +++ b/batch/sql/turn_off_oms_agent_test_dev.py @@ -0,0 +1,20 @@ +import os +import asyncio +from gear import Database + + +async def main(): + if os.environ['HAIL_SCOPE'] == 'deploy': + return + + db = Database() + await db.async_init() + await db.execute_update( + ''' +UPDATE feature_flags +SET oms_agent = 0; +''') + await db.async_close() + +loop = asyncio.get_event_loop() +loop.run_until_complete(main()) diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 798ea0776d6..d6b393c0add 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -48,17 +48,13 @@ def test_job_running_logs(client: BatchClient): j = bb.create_job(DOCKER_ROOT_IMAGE, ['bash', '-c', 'echo test && sleep 300']) b = bb.submit() - delay = 1 - while True: - status = j.status() - if status['state'] == 'Running': - log = j.log() - if log is not None and log['main'] != '': - assert log['main'] == 'test\n', str((log, b.debug_info())) - break - elif status['state'] != 'Ready': - assert False, str((j.log(), b.debug_info())) - delay = sync_sleep_and_backoff(delay) + wait_status = j._wait_for_states('Running') + if wait_status['state'] != 'Running': + assert False, str((j.log(), b.debug_info())) + + log = j.log() + if log is not None and log['main'] != '': + assert log['main'] == 'test\n', str((log, b.debug_info())) b.cancel() b.wait() @@ -603,6 +599,9 @@ def assert_job_ids(expected, q=None): j_success.wait() j_failure.wait() j_error.wait() + wait_status = j_running._wait_for_states('Running') + if wait_status['state'] != 'Running': + assert False, str((b.debug_info(), wait_status)) assert_job_ids({j_success.job_id}, 'state = success') assert_job_ids({j_success.job_id}, 'state == success') @@ -1583,13 +1582,9 @@ def test_update_with_always_run(client: BatchClient): j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], always_run=True, parents=[j1]) b = bb.submit() - delay = 0.1 - while True: - if j1.is_complete(): - assert False, str(j1.status(), b.debug_info()) - if j1.is_running(): - break - delay = sync_sleep_and_backoff(delay) + wait_status = j1._wait_for_states('Running') + if wait_status['state'] != 'Running': + assert False, str(j1.status(), b.debug_info()) assert j2.is_pending(), str(j2.status(), b.debug_info()) @@ -1610,13 +1605,9 @@ def test_update_jobs_are_not_serialized(client: BatchClient): j2.wait() - delay = 0.1 - while True: - if j1.is_complete(): - assert False, str(j1.status(), b.debug_info()) - if j1.is_running(): - break - delay = sync_sleep_and_backoff(delay) + wait_status = j1._wait_for_states('Running') + if wait_status['state'] != 'Running': + assert False, str(j1.status(), b.debug_info()) b.cancel() diff --git a/build.yaml b/build.yaml index c74e5f5b66a..25f6e262d28 100644 --- a/build.yaml +++ b/build.yaml @@ -2311,6 +2311,9 @@ steps: - name: increase-test-max-idle-time script: /io/sql/increase_test_max_idle_time.py online: true + - name: turn_off_oms_agent_test_dev + script: /io/sql/turn_off_oms_agent_test_dev.py + online: true inputs: - from: /repo/batch/sql to: /io/sql @@ -2467,7 +2470,7 @@ steps: - create_certs - kind: runImage name: test_hail_python_service_backend - numSplits: 32 + numSplits: 16 image: valueFrom: hail_run_image.image resources: @@ -2520,7 +2523,7 @@ steps: --ignore=test/hailtop/ \ --timeout=600 \ test - timeout: 2700 + timeout: 5400 inputs: - from: /wheel-container.tar to: /io/wheel-container.tar diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index 4305868c701..266d80e51f8 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -13,7 +13,7 @@ from hailtop.aiocloud.common import Session from hailtop.aiocloud.common.credentials import CloudCredentials from hailtop.auth import hail_credentials -from hailtop.utils import bounded_gather +from hailtop.utils import bounded_gather, sleep_and_backoff from hailtop.utils.rich_progress_bar import is_notebook, BatchProgressBar, BatchProgressBarTask from hailtop import httpx @@ -220,6 +220,9 @@ def _status(self): async def wait(self): return await self._job.wait() + async def _wait_for_states(self, *states: str): + return await self._job._wait_for_states(*states) + async def container_log(self, container_name: str): return await self._job.container_log(container_name) @@ -275,6 +278,9 @@ def _status(self): async def wait(self): raise ValueError("cannot wait on an unsubmitted job") + async def _wait_for_states(self, *states: str): + raise ValueError("cannot _wait_for_states on an unsubmitted job") + async def container_log(self, container_name: str): raise ValueError("cannot get the log of an unsubmitted job") @@ -321,15 +327,14 @@ async def status(self): return self._status async def wait(self): - i = 0 + return await self._wait_for_states(*complete_states) + + async def _wait_for_states(self, *states: str): + delay = 0.1 while True: - if await self.is_complete(): + if await self._is_job_in_state(states) or await self.is_complete(): return self._status - j = random.randrange(math.floor(1.1 ** i)) - await asyncio.sleep(0.100 * j) - # max 44.5s - if i < 64: - i = i + 1 + delay = await sleep_and_backoff(delay) async def container_log(self, container_name: str) -> bytes: async with await self._batch._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/log/{container_name}') as resp: diff --git a/hail/python/hailtop/batch_client/client.py b/hail/python/hailtop/batch_client/client.py index 2b4d6a9ba73..11027e95b87 100644 --- a/hail/python/hailtop/batch_client/client.py +++ b/hail/python/hailtop/batch_client/client.py @@ -115,6 +115,9 @@ def status(self): def wait(self): return async_to_blocking(self._async_job.wait()) + def _wait_for_states(self, *states: str): + return async_to_blocking(self._async_job._wait_for_states(*states)) + def container_log(self, container_name): return async_to_blocking(self._async_job.container_log(container_name)) diff --git a/hail/python/test/hail/conftest.py b/hail/python/test/hail/conftest.py index 63938e08c00..cded225403a 100644 --- a/hail/python/test/hail/conftest.py +++ b/hail/python/test/hail/conftest.py @@ -3,6 +3,7 @@ import os import pytest +import pytest_timeout from hail import current_backend, init, reset_global_randomness from hail.backend.service_backend import ServiceBackend diff --git a/hail/python/test/hail/vds/test_vds_functions.py b/hail/python/test/hail/vds/test_vds_functions.py index 2388bfe6c07..dc4b0a4859d 100644 --- a/hail/python/test/hail/vds/test_vds_functions.py +++ b/hail/python/test/hail/vds/test_vds_functions.py @@ -43,4 +43,9 @@ def test_local_to_global_alleles_non_increasing(): assert hl.eval(hl.vds.local_to_global(lad, local_alleles, 4, 0, number='R')) == [1, 9, 0, 10] assert hl.eval(hl.vds.local_to_global(lpl, local_alleles, 4, 999, number='G')) == [1001, 1002, 1005, 999, 999, 999, 1004, 1003, 999, 0] - assert hl.eval(hl.vds.local_to_global([0, 1, 2, 3, 4, 5], [0, 2, 1], 3, 0, number='G')) == [0, 3, 5, 1, 4, 2] \ No newline at end of file + assert hl.eval(hl.vds.local_to_global([0, 1, 2, 3, 4, 5], [0, 2, 1], 3, 0, number='G')) == [0, 3, 5, 1, 4, 2] + +def test_local_to_global_missing_fill(): + local_alleles = [0, 3, 1] + lad = [1, 10, 9] + assert hl.eval(hl.vds.local_to_global(lad, local_alleles, 4, hl.missing('int32'), number='R')) == [1, 9, None, 10] diff --git a/hail/src/main/scala/is/hail/types/physical/PCanonicalArray.scala b/hail/src/main/scala/is/hail/types/physical/PCanonicalArray.scala index d07e14332f9..62c0dafacfb 100644 --- a/hail/src/main/scala/is/hail/types/physical/PCanonicalArray.scala +++ b/hail/src/main/scala/is/hail/types/physical/PCanonicalArray.scala @@ -491,6 +491,7 @@ final case class PCanonicalArray(elementType: PType, required: Boolean = false) iec.consume(cb, setElementMissing(cb, addr, idx), { sc => + setElementPresent(cb, addr, idx) elementType.storeAtAddress(cb, firstElementAddress + idx.toL * elementByteSize, region, sc, deepCopy = deepCopy) }) } From 3b4253e1eb86905f658142d7cac12102573e8e2c Mon Sep 17 00:00:00 2001 From: Dan King Date: Mon, 31 Jul 2023 12:48:23 -0400 Subject: [PATCH 043/180] [qob] use default parallelism for table parallelize (4, not 16) (#13335) --- hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala index f4a84aade17..d6bbfd263c8 100644 --- a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala +++ b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala @@ -798,7 +798,7 @@ object LowerTableIR { reader.lower(ctx, typ) case TableParallelize(rowsAndGlobal, nPartitions) => - val nPartitionsAdj = nPartitions.getOrElse(16) + val nPartitionsAdj = nPartitions.getOrElse(ctx.backend.defaultParallelism) val loweredRowsAndGlobal = lowerIR(rowsAndGlobal) val loweredRowsAndGlobalRef = Ref(genUID(), loweredRowsAndGlobal.typ) From 15b30d9af63a006beb66a07e516849d44e08c269 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Mon, 31 Jul 2023 18:35:49 -0400 Subject: [PATCH 044/180] [k8s] Dont require access to default secrets when make deploying (#13338) The values of the global config are the same across namespaces, but it does feel more correct to use the `global-config` from the namespace you're targeting than the one in production. This should also enable `make` deploying into a dev namespace without having any permissions for `default`. --- config.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.mk b/config.mk index e015bce2043..eb1ec7cc84f 100644 --- a/config.mk +++ b/config.mk @@ -1,9 +1,9 @@ # These values should be lazy so you don't need kubectl for targets that don't # require it but also only evaluated at most once every make invocation # https://make.mad-scientist.net/deferred-simple-variable-expansion/ -DOCKER_PREFIX = $(eval DOCKER_PREFIX := $$(shell kubectl get secret global-config --template={{.data.docker_prefix}} | base64 --decode))$(DOCKER_PREFIX) -DOMAIN = $(eval DOMAIN := $$(shell kubectl get secret global-config --template={{.data.domain}} | base64 --decode))$(DOMAIN) -CLOUD = $(eval CLOUD := $$(shell kubectl get secret global-config --template={{.data.cloud}} | base64 --decode))$(CLOUD) +DOCKER_PREFIX = $(eval DOCKER_PREFIX := $$(shell kubectl -n $(NAMESPACE) get secret global-config --template={{.data.docker_prefix}} | base64 --decode))$(DOCKER_PREFIX) +DOMAIN = $(eval DOMAIN := $$(shell kubectl -n $(NAMESPACE) get secret global-config --template={{.data.domain}} | base64 --decode))$(DOMAIN) +CLOUD = $(eval CLOUD := $$(shell kubectl -n $(NAMESPACE) get secret global-config --template={{.data.cloud}} | base64 --decode))$(CLOUD) ifeq ($(NAMESPACE),default) SCOPE = deploy From d6af81a5fb87dbb0a082c37178c248359b58da20 Mon Sep 17 00:00:00 2001 From: Dan King Date: Mon, 31 Jul 2023 23:03:23 -0400 Subject: [PATCH 045/180] [security] delete after 5 days, ignore system managed, consider two special secrets (#13319) A job running for five days *could* cause an issue here, so the operator should still be cognizant of that. The move to access tokens will eliminate that concern anyway. We should not consider system-managed keys because those are managed by Google and not even visible in the UI. We are not obligated to rotate them (nor are we able, afaik). There are two special secrets which do not conform to the `key.json` naming scheme for their secret files. I added them as special cases. --- devbin/rotate_keys.py | 109 +++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 49 deletions(-) diff --git a/devbin/rotate_keys.py b/devbin/rotate_keys.py index bce6aba4c5f..5da0610c2c1 100644 --- a/devbin/rotate_keys.py +++ b/devbin/rotate_keys.py @@ -29,7 +29,7 @@ class ServiceAccountDict(TypedDict): name: str projectId: str - uniqueId: str + uniqueId: str email: str displayName: str etag: str @@ -46,10 +46,11 @@ class RotationState(Enum): class GSAKeySecret: - def __init__(self, raw_secret): + def __init__(self, raw_secret, key_file_name: str): self.name = raw_secret.metadata.name self.namespace = raw_secret.metadata.namespace - self.key_data = json.loads(base64.b64decode(raw_secret.data['key.json'])) + self.key_data = json.loads(base64.b64decode(raw_secret.data[key_file_name])) + self.key_file_name = key_file_name def service_account_email(self): return self.key_data['client_email'] @@ -60,6 +61,9 @@ def private_key_id(self): def matches_iam_key(self, k: 'IAMKey'): return self.private_key_id() == k.id + def to_data_dict(self, key_data: str) -> Dict[str, str]: + return {self.key_file_name: key_data} + def __str__(self): return f'{self.name} ({self.namespace})' @@ -68,29 +72,34 @@ class KubeSecretManager: def __init__(self, kube_client): self.kube_client = kube_client - async def get_gsa_key_secrets(self) -> List[GSAKeySecret]: - secrets = (await retry_transient_errors(self.kube_client.list_secret_for_all_namespaces)).items - return [GSAKeySecret(s) for s in secrets if s.data is not None and 'key.json' in s.data] - async def get_secrets(self) -> Tuple[Any, List[GSAKeySecret]]: secrets = (await retry_transient_errors(self.kube_client.list_secret_for_all_namespaces)).items return ( - [s for s in secrets - if (s.data is None or 'key.json' not in s.data) - and not s.metadata.name.endswith('-tokens') - and not s.metadata.name.startswith('ssl-config-') - and not (s.metadata.name.startswith('sql-') and s.metadata.name.endswith('-config')) - and s.metadata.name not in ('database-server-config', 'ci-config', 'deploy-config', 'gce-deploy-config') - and not s.metadata.namespace == 'kube-system' - and not s.type == 'kubernetes.io/service-account-token'], - [GSAKeySecret(s) for s in secrets if s.data is not None and 'key.json' in s.data] + [ + s + for s in secrets + if (s.data is None or 'key.json' not in s.data) + and not s.metadata.name.endswith('-tokens') + and not s.metadata.name.startswith('ssl-config-') + and not (s.metadata.name.startswith('sql-') and s.metadata.name.endswith('-config')) + and s.metadata.name not in ('database-server-config', 'ci-config', 'deploy-config', 'gce-deploy-config') + and not s.metadata.namespace == 'kube-system' + and not s.type == 'kubernetes.io/service-account-token' + ], + [GSAKeySecret(s, 'key.json') for s in secrets if s.data is not None and 'key.json' in s.data] + + [ + GSAKeySecret(s, 'test-dataproc-service-account-key.json') + for s in secrets + if s.metadata.name == 'test-dataproc-service-account-key' + ] + + [GSAKeySecret(s, 'credentials.json') for s in secrets if s.metadata.name == 'registry-push-credentials'], ) async def update_gsa_key_secret(self, secret: GSAKeySecret, key_data: str) -> GSAKeySecret: - data = {'key.json': key_data} + data = secret.to_data_dict(key_data) await self.update_secret(secret.name, secret.namespace, data) print(f'Updated secret {secret}') - return GSAKeySecret(await self.get_secret(secret.name, secret.namespace)) + return GSAKeySecret(await self.get_secret(secret.name, secret.namespace), secret.key_file_name) async def update_secret(self, name, namespace, data): await retry_transient_errors( @@ -126,7 +135,7 @@ def soon_to_expire(self) -> bool: return self.older_than(60) def recently_created(self) -> bool: - return not self.older_than(30) + return not self.older_than(5) def older_than(self, days: int) -> bool: return self.created < datetime.now(pytz.utc) - timedelta(days=days) @@ -195,17 +204,16 @@ def active_user_key(self) -> Optional[IAMKey]: for s in self.kube_secrets: keys_to_k8s_secret[s.private_key_id()].append((s.name, s.namespace)) keys_to_k8s_secret_str = "\n".join( - f'{k} ' + ", ".join(str(s) for s in secrets) - for k, secrets in keys_to_k8s_secret.items() + f'{k} ' + ", ".join(str(s) for s in secrets) for k, secrets in keys_to_k8s_secret.items() ) known_iam_keys_str = "\n".join( f'{k.id} Created: {k.created_readable} Expires: {k.expiration_readable}' for k in self.keys ) kube_key = sorted( - [k for k in self.keys - if k.id in keys_to_k8s_secret], - key=lambda k: -k.created.timestamp())[0] - print(f'''Found a user ({self.username()}) without a unique active key in Kubernetes. + [k for k in self.keys if k.id in keys_to_k8s_secret], key=lambda k: -k.created.timestamp() + )[0] + print( + f'''Found a user ({self.username()}) without a unique active key in Kubernetes. The known IAM keys are: {known_iam_keys_str} @@ -213,7 +221,8 @@ def active_user_key(self) -> Optional[IAMKey]: {keys_to_k8s_secret_str} We will assume {kube_key.id} is the active key. -''') +''' + ) assert kube_key is not None assert kube_key.user_managed return kube_key @@ -256,13 +265,11 @@ async def get_all_service_accounts(self) -> List[ServiceAccount]: return all_accounts async def service_account_from_dict(self, d: ServiceAccountDict) -> ServiceAccount: - return ServiceAccount(d['email'], - d.get('disabled', False), - await self.get_sa_keys(d['email'])) + return ServiceAccount(d['email'], d.get('disabled', False), await self.get_sa_keys(d['email'])) async def get_sa_keys(self, sa_email: str) -> List[IAMKey]: keys_json = (await self.iam_client.get(f'/serviceAccounts/{sa_email}/keys'))['keys'] - keys = [IAMKey(k) for k in keys_json] + keys = [IAMKey(k) for k in keys_json if k['keyType'] != 'SYSTEM_MANAGED'] keys.sort(key=lambda k: k.created) keys.reverse() return keys @@ -279,17 +286,17 @@ async def all_sa_dicts(self) -> Generator[ServiceAccountDict, None, None]: yield acc -async def add_new_keys(service_accounts: List[ServiceAccount], - iam_manager: IAMManager, - k8s_manager: KubeSecretManager, - *, - exclude: Optional[Set[RotationState]] = None, - interactive: bool): +async def add_new_keys( + service_accounts: List[ServiceAccount], + iam_manager: IAMManager, + k8s_manager: KubeSecretManager, + *, + exclude: Optional[Set[RotationState]] = None, + interactive: bool, +): exclude = exclude or {} service_accounts_under_consideration = [ - sa - for sa in service_accounts - if not sa.disabled and sa.rotation_state() not in exclude + sa for sa in service_accounts if not sa.disabled and sa.rotation_state() not in exclude ] if not interactive: accounts_str = '\n'.join(str(sa) for sa in service_accounts_under_consideration) @@ -306,14 +313,14 @@ async def add_new_keys(service_accounts: List[ServiceAccount], new_key, key_data = await iam_manager.create_new_key(sa) sa.add_new_key(new_key) print(f'Created new key: {new_key.id}') - new_secrets = await asyncio.gather( - *[k8s_manager.update_gsa_key_secret(s, key_data) for s in sa.kube_secrets] - ) + new_secrets = await asyncio.gather(*[k8s_manager.update_gsa_key_secret(s, key_data) for s in sa.kube_secrets]) sa.kube_secrets = list(new_secrets) sa.list_keys(sys.stdout) -async def delete_old_keys(service_accounts: List[ServiceAccount], iam_manager: IAMManager, focus: Optional[RotationState] = None): +async def delete_old_keys( + service_accounts: List[ServiceAccount], iam_manager: IAMManager, focus: Optional[RotationState] = None +): async def delete_old_and_refresh(sa: ServiceAccount): to_delete = sa.redundant_user_keys() await asyncio.gather(*[iam_manager.delete_key(sa.email, k) for k in to_delete]) @@ -402,13 +409,17 @@ async def main(): for secret in other_secrets: print(f'\t{secret.metadata.name} ({secret.metadata.namespace})') - action = input('What action would you like to take?[update/interactive-update/delete/delete-ready-only/delete-in-progress-only]: ') + action = input( + 'What action would you like to take?[update/interactive-update/delete/delete-ready-only/delete-in-progress-only]: ' + ) if action == 'update': - await add_new_keys(service_accounts, iam_manager, k8s_manager, - exclude={RotationState.UP_TO_DATE, - RotationState.IN_PROGRESS, - RotationState.READY_FOR_DELETE}, - interactive=False) + await add_new_keys( + service_accounts, + iam_manager, + k8s_manager, + exclude={RotationState.UP_TO_DATE, RotationState.IN_PROGRESS, RotationState.READY_FOR_DELETE}, + interactive=False, + ) if action == 'interactive-update': await add_new_keys(service_accounts, iam_manager, k8s_manager, interactive=True) elif action == 'delete': From fa41ed71f348573f5142ed0d8f03876eb3662006 Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 1 Aug 2023 13:56:10 -0400 Subject: [PATCH 046/180] [azure] Add connection timeouts for Azure FS in both Python and Scala (#13344) I hope this helps. The regular `timeout` parameter on the Python methods like `stage_block` is for the server-side timeout of the operation. We want the client side timeout to be shorter. I picked 5 seconds, but that was arbitrary. I'm not sure I implemented the Scala code correctly, but that's along the right lines of what needs to happen. --- hail/python/hailtop/aiocloud/aioazure/fs.py | 12 +++++++++-- .../scala/is/hail/io/fs/AzureStorageFS.scala | 21 +++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/hail/python/hailtop/aiocloud/aioazure/fs.py b/hail/python/hailtop/aiocloud/aioazure/fs.py index 0263d096cc9..868d03379da 100644 --- a/hail/python/hailtop/aiocloud/aioazure/fs.py +++ b/hail/python/hailtop/aiocloud/aioazure/fs.py @@ -341,7 +341,11 @@ async def wrapped(self: 'AzureAsyncFS', url, *args, **kwargs): return await fun(self, url, *args, **kwargs) except azure.core.exceptions.ClientAuthenticationError: fs_url = self.parse_url(url) - anon_client = BlobServiceClient(f'https://{fs_url.account}.blob.core.windows.net', credential=None) + # https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/storage/azure-storage-blob#other-client--per-operation-configuration + anon_client = BlobServiceClient(f'https://{fs_url.account}.blob.core.windows.net', + credential=None, + connection_timeout=5, + read_timeout=5) self._blob_service_clients[(fs_url.account, fs_url.container, fs_url.query)] = anon_client return await fun(self, url, *args, **kwargs) return wrapped @@ -451,7 +455,11 @@ def get_blob_service_client(self, account: str, container: str, token: Optional[ credential = token if token else self._credential k = account, container, token if k not in self._blob_service_clients: - self._blob_service_clients[k] = BlobServiceClient(f'https://{account}.blob.core.windows.net', credential=credential) + # https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/storage/azure-storage-blob#other-client--per-operation-configuration + self._blob_service_clients[k] = BlobServiceClient(f'https://{account}.blob.core.windows.net', + credential=credential, + connection_timeout=5, + read_timeout=5) return self._blob_service_clients[k] def get_blob_client(self, url: AzureAsyncFSURL) -> BlobClient: diff --git a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala index e49ee180286..3d47b2c3583 100644 --- a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala @@ -2,13 +2,14 @@ package is.hail.io.fs import is.hail.shadedazure.com.azure.core.credential.{AzureSasCredential, TokenCredential} import is.hail.shadedazure.com.azure.identity.{ClientSecretCredential, ClientSecretCredentialBuilder, DefaultAzureCredential, DefaultAzureCredentialBuilder, ManagedIdentityCredentialBuilder} -import is.hail.shadedazure.com.azure.storage.blob.models.{BlobProperties, BlobRange, ListBlobsOptions, BlobStorageException} +import is.hail.shadedazure.com.azure.storage.blob.models.{BlobProperties, BlobRange, BlobStorageException, ListBlobsOptions} import is.hail.shadedazure.com.azure.storage.blob.specialized.BlockBlobClient import is.hail.shadedazure.com.azure.storage.blob.{BlobClient, BlobContainerClient, BlobServiceClient, BlobServiceClientBuilder} -import is.hail.shadedazure.com.azure.core.http.netty.NettyAsyncHttpClientBuilder -import is.hail.shadedazure.reactor.netty.http.client.HttpClient +import is.hail.shadedazure.com.azure.core.http.HttpClient +import is.hail.shadedazure.com.azure.core.util.HttpClientOptions import is.hail.services.retryTransientErrors import is.hail.io.fs.FSUtil.{containsWildcard, dropTrailingSlash} +import is.hail.services.Requester.httpClient import org.apache.log4j.Logger import org.apache.commons.io.IOUtils @@ -148,7 +149,7 @@ object AzureStorageFileStatus { } } -class AzureBlobServiceClientCache(credential: TokenCredential) { +class AzureBlobServiceClientCache(credential: TokenCredential, val httpClientOptions: HttpClientOptions) { private[this] lazy val clients = mutable.Map[(String, String, Option[String]), BlobServiceClient]() def getServiceClient(url: AzureStorageFSURL): BlobServiceClient = { @@ -164,6 +165,7 @@ class AzureBlobServiceClientCache(credential: TokenCredential) { val blobServiceClient = clientBuilder .endpoint(s"https://${url.account}.blob.core.windows.net") + .clientOptions(httpClientOptions) .buildClient() clients += (k -> blobServiceClient) blobServiceClient @@ -173,6 +175,7 @@ class AzureBlobServiceClientCache(credential: TokenCredential) { def setPublicAccessServiceClient(url: AzureStorageFSURL): Unit = { val blobServiceClient = new BlobServiceClientBuilder() .endpoint(s"https://${url.account}.blob.core.windows.net") + .clientOptions(httpClientOptions) .buildClient() clients += ((url.account, url.container, url.sasToken) -> blobServiceClient) } @@ -212,10 +215,16 @@ class AzureStorageFS(val credentialsJSON: Option[String] = None) extends FS { } } + private lazy val httpClientOptions = new HttpClientOptions() + .setReadTimeout(Duration.ofSeconds(5)) + .setConnectTimeout(Duration.ofSeconds(5)) + .setConnectionIdleTimeout(Duration.ofSeconds(5)) + .setWriteTimeout(Duration.ofSeconds(5)) + private lazy val serviceClientCache = credentialsJSON match { case None => val credential: DefaultAzureCredential = new DefaultAzureCredentialBuilder().build() - new AzureBlobServiceClientCache(credential) + new AzureBlobServiceClientCache(credential, httpClientOptions) case Some(keyData) => implicit val formats: Formats = defaultJSONFormats val kvs = JsonMethods.parse(keyData) @@ -228,7 +237,7 @@ class AzureStorageFS(val credentialsJSON: Option[String] = None) extends FS { .clientSecret(password) .tenantId(tenant) .build() - new AzureBlobServiceClientCache(clientSecretCredential) + new AzureBlobServiceClientCache(clientSecretCredential, httpClientOptions) } // Set to max timeout for blob storage of 30 seconds From 0e5419f52ccb3a86db65c40c99e467b67bafe1fd Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 1 Aug 2023 16:36:53 -0400 Subject: [PATCH 047/180] [qob] disable QoB PR tests (keep deploy and dev) (#13353) For added context see: https://github.com/hail-is/hail/issues/13351 cc: @patrick-schultz @chrisvittal @daniel-goldstein @ehigham @iris-garden I actually don't think we need to notify anyone because we'll still get errors if something goes wrong in default. If main starts failing, we have the slightly annoying situation of needing to run tests in a one-off manner to verify and we might need to block a release until we can revert. --- build.yaml | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 4 deletions(-) diff --git a/build.yaml b/build.yaml index 25f6e262d28..b3c838f3bc3 100644 --- a/build.yaml +++ b/build.yaml @@ -2469,7 +2469,7 @@ steps: - deploy_memory_sa - create_certs - kind: runImage - name: test_hail_python_service_backend + name: test_hail_python_service_backend_gcp numSplits: 16 image: valueFrom: hail_run_image.image @@ -2554,6 +2554,99 @@ steps: - upload_test_resources_to_blob_storage - build_hail_jar_and_wheel - hailgenetics_vep_grch37_85_image + clouds: + - gcp + - kind: runImage + name: test_hail_python_service_backend_azure + numSplits: 16 + image: + valueFrom: hail_run_image.image + resources: + cpu: '0.25' + preemptible: False + script: | + set -ex + tar xvf /io/wheel-container.tar + python3 -m pip install --no-dependencies hail-*-py3-none-any.whl + + cd /io/repo/hail/python + + export HAIL_CLOUD={{ global.cloud }} + export HAIL_TEST_STORAGE_URI={{ global.test_storage_uri }}/{{ token }} + export HAIL_TEST_RESOURCES_DIR="{{ global.test_storage_uri }}/{{ upload_test_resources_to_blob_storage.token }}/test/resources/" + export HAIL_DOCTEST_DATA_DIR="{{ global.test_storage_uri }}/{{ upload_test_resources_to_blob_storage.token }}/doctest/data/" + export HAIL_GENETICS_VEP_GRCH37_85_IMAGE={{ hailgenetics_vep_grch37_85_image.image }} + export GOOGLE_APPLICATION_CREDENTIALS=/test-gsa-key/key.json + export AZURE_APPLICATION_CREDENTIALS=/test-gsa-key/key.json + + {% if global.cloud == "gcp" %} + export GCS_REQUESTER_PAYS_PROJECT=broad-ctsa + {% elif global.cloud == "azure" %} + export HAIL_AZURE_SUBSCRIPTION_ID={{ global.azure_subscription_id }} + export HAIL_AZURE_RESOURCE_GROUP={{ global.azure_resource_group }} + {% endif %} + + export HAIL_SHUFFLE_MAX_BRANCH=4 + export HAIL_SHUFFLE_CUTOFF=1000000 + export HAIL_QUERY_BACKEND=batch + {% if global.cloud == "azure" %} + export HAIL_BATCH_REGIONS={{ global.azure_location }} + {% elif global.cloud == "gcp" %} + export HAIL_BATCH_REGIONS={{ global.gcp_region }} + {% else %} + echo "unknown cloud {{ global.cloud }}" + exit 1 + {% endif %} + export HAIL_BATCH_BILLING_PROJECT=test + export HAIL_BATCH_REMOTE_TMPDIR={{ global.test_storage_uri }} + + python3 -m pytest \ + -Werror:::hail -Werror:::hailtop -Werror::ResourceWarning \ + --log-cli-level=INFO \ + -s \ + -r A \ + -vv \ + --instafail \ + --durations=50 \ + --ignore=test/hailtop/ \ + --timeout=600 \ + test + timeout: 5400 + inputs: + - from: /wheel-container.tar + to: /io/wheel-container.tar + - from: /repo/hail/python/test + to: /io/repo/hail/python/test + secrets: + - name: test-gsa-key + namespace: + valueFrom: default_ns.name + mountPath: /test-gsa-key + - name: worker-deploy-config + namespace: + valueFrom: default_ns.name + mountPath: /deploy-config + - name: test-tokens + namespace: + valueFrom: default_ns.name + mountPath: /user-tokens + dependsOn: + - default_ns + - merge_code + - deploy_batch + - deploy_memory + - create_deploy_config + - create_accounts + - hail_run_image + - upload_query_jar + - upload_test_resources_to_blob_storage + - build_hail_jar_and_wheel + - hailgenetics_vep_grch37_85_image + scopes: + - deploy + - dev + clouds: + - azure - kind: runImage name: test_hail_spark_conf_requester_pays_parsing image: @@ -3710,7 +3803,8 @@ steps: - test_batch - test_ci - test_hailtop_batch - - test_hail_python_service_backend + - test_hail_python_service_backend_gcp + - test_hail_python_service_backend_azure - test_hail_services_java - test_batch_docs - test_hailctl_batch @@ -3759,7 +3853,8 @@ steps: - test_batch - test_ci - test_hailtop_batch - - test_hail_python_service_backend + - test_hail_python_service_backend_gcp + - test_hail_python_service_backend_azure - cancel_all_running_test_batches - kind: runImage name: delete_gcp_batch_instances @@ -3805,7 +3900,8 @@ steps: - test_batch - test_ci - test_hailtop_batch - - test_hail_python_service_backend + - test_hail_python_service_backend_gcp + - test_hail_python_service_backend_azure - cancel_all_running_test_batches - kind: runImage name: delete_azure_batch_instances @@ -3854,4 +3950,6 @@ steps: - test_batch - test_ci - test_hailtop_batch + - test_hail_python_service_backend_gcp + - test_hail_python_service_backend_azure - cancel_all_running_test_batches From ceb343b22ef9096c3b06428c10ca6886fea3581f Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 1 Aug 2023 17:45:48 -0400 Subject: [PATCH 048/180] [services] use AWS-inspired retry delays (#13354) The first major change is that the base delay is now never below 1s. Previously our base delay was often 100ms. The second major change is that I implemented the "Equal Jitter" algorithm from AWS's page on [backoff and jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/). --- batch/batch/resource_usage.py | 7 +- batch/batch/worker/worker_api.py | 11 +- batch/test/test_batch.py | 12 +- gear/gear/database.py | 7 +- .../aiocloud/aioazure/client/base_client.py | 7 +- .../aiogoogle/client/compute_client.py | 8 +- hail/python/hailtop/batch_client/aioclient.py | 7 +- .../hailtop/hailctl/auth/create_user.py | 7 +- .../hailtop/hailctl/auth/delete_user.py | 7 +- .../hailtop/hailctl/hdinsight/submit.py | 7 +- hail/python/hailtop/utils/__init__.py | 9 +- hail/python/hailtop/utils/utils.py | 109 ++++++++++-------- .../hailtop/batch/test_batch_pool_executor.py | 7 +- .../main/scala/is/hail/services/package.scala | 44 +++++-- 14 files changed, 149 insertions(+), 100 deletions(-) diff --git a/batch/batch/resource_usage.py b/batch/batch/resource_usage.py index b5d4f7c24c2..ac2b1ec9a98 100644 --- a/batch/batch/resource_usage.py +++ b/batch/batch/resource_usage.py @@ -11,7 +11,7 @@ import pandas as pd from hailtop.aiotools.fs import AsyncFS -from hailtop.utils import check_shell_output, sleep_and_backoff, time_msecs, time_ns +from hailtop.utils import check_shell_output, sleep_before_try, time_msecs, time_ns log = logging.getLogger('resource_usage') @@ -233,7 +233,7 @@ async def read(self): async def __aenter__(self): async def periodically_measure(): cancelled = False - delay = 0.1 + tries = 0 while True: try: await self.measure() @@ -249,7 +249,8 @@ async def periodically_measure(): log.exception(f'while monitoring {self.container_name}') finally: if not cancelled: - delay = await sleep_and_backoff(delay, 5) + tries += 1 + await sleep_before_try(tries, max_delay_ms=5_000) os.makedirs(os.path.dirname(self.output_file_path), exist_ok=True) self.out = open(self.output_file_path, 'wb') # pylint: disable=consider-using-with diff --git a/batch/batch/worker/worker_api.py b/batch/batch/worker/worker_api.py index 5412ebc8a90..238469f35af 100644 --- a/batch/batch/worker/worker_api.py +++ b/batch/batch/worker/worker_api.py @@ -5,7 +5,7 @@ from hailtop import httpx from hailtop.aiotools.fs import AsyncFS -from hailtop.utils import CalledProcessError, sleep_and_backoff +from hailtop.utils import CalledProcessError, sleep_before_try from ..instance_config import InstanceConfig from .credentials import CloudUserCredentials @@ -63,17 +63,16 @@ async def mount_cloudfuse( mount_base_path_tmp: str, config: dict, ) -> None: - delay = 0.1 - error = 0 + tries = 0 while True: try: return await self._mount_cloudfuse(credentials, mount_base_path_data, mount_base_path_tmp, config) except CalledProcessError: - error += 1 - if error == 5: + tries += 1 + if tries == 5: raise - delay = await sleep_and_backoff(delay) + await sleep_before_try(tries) @abc.abstractmethod async def unmount_cloudfuse(self, mount_base_path_data: str) -> None: diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index d6b393c0add..336ab2d6a9a 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -13,7 +13,7 @@ from hailtop.batch_client.client import BatchClient from hailtop.config import get_deploy_config, get_user_config from hailtop.test_utils import skip_in_azure -from hailtop.utils import external_requests_client_session, retry_response_returning_functions, sync_sleep_and_backoff +from hailtop.utils import delay_ms_for_try, external_requests_client_session, retry_response_returning_functions from hailtop.utils.rich_progress_bar import BatchProgressBar from .failure_injecting_client_session import FailureInjectingClientSession @@ -1464,16 +1464,20 @@ def test_job_private_instance_cancel(client: BatchClient): j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) b = bb.submit() - delay = 0.1 + tries = 0 start = time.time() while True: status = j.status() if status['state'] == 'Creating': break now = time.time() - if now + delay - start > 60: + + tries += 1 + cumulative_delay = now - start + if cumulative_delay > 60: assert False, str((status, b.debug_info())) - delay = sync_sleep_and_backoff(delay) + delay = min(delay_ms_for_try(tries), 60 - cumulative_delay) + time.sleep(delay) b.cancel() status = j.wait() assert status['state'] == 'Cancelled', str((status, b.debug_info())) diff --git a/gear/gear/database.py b/gear/gear/database.py index 3b2da5f4e51..a240eb6253e 100644 --- a/gear/gear/database.py +++ b/gear/gear/database.py @@ -15,7 +15,7 @@ from hailtop.aiotools import BackgroundTaskManager from hailtop.auth.sql_config import SQLConfig from hailtop.config import get_deploy_config -from hailtop.utils import sleep_and_backoff +from hailtop.utils import sleep_before_try log = logging.getLogger('gear.database') @@ -32,7 +32,7 @@ def retry_transient_mysql_errors(f): @functools.wraps(f) async def wrapper(*args, **kwargs): - delay = 0.1 + tries = 0 while True: try: return await f(*args, **kwargs) @@ -54,7 +54,8 @@ async def wrapper(*args, **kwargs): ) else: raise - delay = await sleep_and_backoff(delay) + tries += 1 + await sleep_before_try(tries) return wrapper diff --git a/hail/python/hailtop/aiocloud/aioazure/client/base_client.py b/hail/python/hailtop/aiocloud/aioazure/client/base_client.py index 533dabb7a83..74257649db6 100644 --- a/hail/python/hailtop/aiocloud/aioazure/client/base_client.py +++ b/hail/python/hailtop/aiocloud/aioazure/client/base_client.py @@ -1,7 +1,7 @@ from typing import Optional, AsyncGenerator, Any import aiohttp -from hailtop.utils import RateLimit, sleep_and_backoff, url_and_params +from hailtop.utils import RateLimit, sleep_before_try, url_and_params from ...common import CloudBaseClient from ..session import AzureSession @@ -36,9 +36,10 @@ async def delete(self, path: Optional[str] = None, *, url: Optional[str] = None, return resp async def delete_and_wait(self, path: Optional[str] = None, *, url: Optional[str] = None, **kwargs) -> aiohttp.ClientResponse: - delay = 5 + tries = 1 while True: resp = await self.delete(path, url=url, **kwargs) if resp.status == 204: return resp - delay = await sleep_and_backoff(delay) + tries += 1 + await sleep_before_try(tries, base_delay_ms=5_000) diff --git a/hail/python/hailtop/aiocloud/aiogoogle/client/compute_client.py b/hail/python/hailtop/aiocloud/aiogoogle/client/compute_client.py index ade5398113d..baa84c8bc59 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/client/compute_client.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/client/compute_client.py @@ -3,7 +3,7 @@ import logging import aiohttp -from hailtop.utils import retry_transient_errors, sleep_and_backoff +from hailtop.utils import retry_transient_errors, sleep_before_try from .base_client import GoogleBaseClient @@ -100,7 +100,7 @@ async def request_and_wait(): operation_id = resp['id'] zone = resp['zone'].rsplit('/', 1)[1] - delay = 2 + tries = 0 while True: result = await self.post(f'/zones/{zone}/operations/{operation_id}/wait', timeout=aiohttp.ClientTimeout(total=150)) @@ -120,7 +120,7 @@ async def request_and_wait(): result) return result - - delay = await sleep_and_backoff(delay, max_delay=15) + tries += 1 + await sleep_before_try(tries, base_delay_ms=2_000, max_delay_ms=15_000) return await retry_transient_errors(request_and_wait) diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index 266d80e51f8..631eca09a8d 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -13,7 +13,7 @@ from hailtop.aiocloud.common import Session from hailtop.aiocloud.common.credentials import CloudCredentials from hailtop.auth import hail_credentials -from hailtop.utils import bounded_gather, sleep_and_backoff +from hailtop.utils import bounded_gather, sleep_before_try from hailtop.utils.rich_progress_bar import is_notebook, BatchProgressBar, BatchProgressBarTask from hailtop import httpx @@ -330,11 +330,12 @@ async def wait(self): return await self._wait_for_states(*complete_states) async def _wait_for_states(self, *states: str): - delay = 0.1 + tries = 0 while True: if await self._is_job_in_state(states) or await self.is_complete(): return self._status - delay = await sleep_and_backoff(delay) + tries += 1 + await sleep_before_try(tries) async def container_log(self, container_name: str) -> bytes: async with await self._batch._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/log/{container_name}') as resp: diff --git a/hail/python/hailtop/hailctl/auth/create_user.py b/hail/python/hailtop/hailctl/auth/create_user.py index 061aa8495f6..dab152d6b3f 100644 --- a/hail/python/hailtop/hailctl/auth/create_user.py +++ b/hail/python/hailtop/hailctl/auth/create_user.py @@ -1,6 +1,6 @@ from typing import Optional -from hailtop.utils import sleep_and_backoff +from hailtop.utils import sleep_before_try from hailtop.auth import async_create_user, async_get_user @@ -26,14 +26,15 @@ async def polling_create_user( return async def _poll(): - delay = 5 + tries = 0 while True: user = await async_get_user(username, namespace) if user['state'] == 'active': print(f"Created user '{username}'") return assert user['state'] == 'creating' - delay = await sleep_and_backoff(delay) + tries += 1 + await sleep_before_try(tries, base_delay_ms = 5_000) await _poll() except Exception as e: diff --git a/hail/python/hailtop/hailctl/auth/delete_user.py b/hail/python/hailtop/hailctl/auth/delete_user.py index 9ebb7709304..fad558d98b0 100644 --- a/hail/python/hailtop/hailctl/auth/delete_user.py +++ b/hail/python/hailtop/hailctl/auth/delete_user.py @@ -1,6 +1,6 @@ from typing import Optional -from hailtop.utils import sleep_and_backoff +from hailtop.utils import sleep_before_try from hailtop.auth import async_delete_user, async_get_user @@ -20,14 +20,15 @@ async def polling_delete_user( return async def _poll(): - delay = 5 + tries = 1 while True: user = await async_get_user(username, namespace) if user['state'] == 'deleted': print(f"Deleted user '{username}'") return assert user['state'] == 'deleting' - delay = await sleep_and_backoff(delay) + tries += 1 + await sleep_before_try(tries, base_delay_ms = 5_000) await _poll() except Exception as e: diff --git a/hail/python/hailtop/hailctl/hdinsight/submit.py b/hail/python/hailtop/hailctl/hdinsight/submit.py index 61a28a74b24..4b0544ae18a 100644 --- a/hail/python/hailtop/hailctl/hdinsight/submit.py +++ b/hail/python/hailtop/hailctl/hdinsight/submit.py @@ -13,7 +13,7 @@ def submit( ): import requests # pylint: disable=import-outside-toplevel import requests.auth # pylint: disable=import-outside-toplevel - from ...utils import sync_sleep_and_backoff # pylint: disable=import-outside-toplevel + from ...utils import sync_sleep_before_try # pylint: disable=import-outside-toplevel print("Submitting to cluster '{}'...".format(name)) @@ -47,7 +47,7 @@ def submit( resp.raise_for_status() batch_id = batch['id'] - delay = 0.01 + tries = 1 while True: resp = requests.get( f'https://{name}.azurehdinsight.net/livy/batches/{batch_id}', @@ -61,4 +61,5 @@ def submit( f'Job submitted. View logs at: https://{name}.azurehdinsight.net/yarnui/hn/cluster/app/{batch["appId"]}' ) break - delay = sync_sleep_and_backoff(delay) + tries += 1 + sync_sleep_before_try(tries, base_delay_ms = 10) diff --git a/hail/python/hailtop/utils/__init__.py b/hail/python/hailtop/utils/__init__.py index 2d7080f85f2..35e18fafc89 100644 --- a/hail/python/hailtop/utils/__init__.py +++ b/hail/python/hailtop/utils/__init__.py @@ -2,7 +2,7 @@ time_msecs, time_msecs_str, humanize_timedelta_msecs, parse_timestamp_msecs, time_ns) from .utils import (unzip, async_to_blocking, blocking_to_async, AsyncWorkerPool, bounded_gather, - grouped, sync_sleep_and_backoff, sleep_and_backoff, is_transient_error, + grouped, sync_sleep_before_try, sleep_before_try, is_transient_error, collect_agen, retry_all_errors, retry_transient_errors, retry_transient_errors_with_debug_string, retry_long_running, run_if_changed, run_if_changed_idempotent, LoggingTimer, WaitableSharedPool, @@ -15,7 +15,7 @@ unpack_comma_delimited_inputs, unpack_key_value_inputs, retry_all_errors_n_times, Timings, is_limited_retries_error, am_i_interactive, is_delayed_warning_error, retry_transient_errors_with_delayed_warnings, - periodically_call_with_dynamic_sleep) + periodically_call_with_dynamic_sleep, delay_ms_for_try) from .process import ( CalledProcessError, check_shell, check_shell_output, check_exec_output, sync_check_shell, sync_check_shell_output, sync_check_exec) @@ -47,8 +47,9 @@ 'grouped', 'is_transient_error', 'is_delayed_warning_error', - 'sync_sleep_and_backoff', - 'sleep_and_backoff', + 'sync_sleep_before_try', + 'sleep_before_try', + 'delay_ms_for_try', 'retry_all_errors', 'retry_transient_errors', 'retry_transient_errors_with_debug_string', diff --git a/hail/python/hailtop/utils/utils.py b/hail/python/hailtop/utils/utils.py index 233a82af5cf..b3c22db9bb9 100644 --- a/hail/python/hailtop/utils/utils.py +++ b/hail/python/hailtop/utils/utils.py @@ -721,24 +721,44 @@ def is_delayed_warning_error(e): return False -async def sleep_and_backoff(delay, max_delay=30.0): - # exponentially back off, up to (expected) max_delay - t = delay * random.uniform(0.9, 1.1) - await asyncio.sleep(t) - return min(delay * 2, max_delay) +LOG_2_MAX_MULTIPLIER = 30 # do not set larger than 30 to avoid BigInt arithmetic +DEFAULT_MAX_DELAY_MS = 60_000 +DEFAULT_BASE_DELAY_MS = 1_000 -def sync_sleep_and_backoff(delay): - # exponentially back off, up to (expected) max of 30s - t = delay * random.uniform(0.9, 1.1) - time.sleep(t) - return min(delay * 2, 30.0) +def delay_ms_for_try( + tries: int, + base_delay_ms: int = DEFAULT_BASE_DELAY_MS, + max_delay_ms: int = DEFAULT_MAX_DELAY_MS +) -> int: + # Based on AWS' recommendations: + # - https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ + # - https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedBackoffStrategies.java + multiplier = 1 << min(tries, LOG_2_MAX_MULTIPLIER) + ceiling_for_delay_ms = base_delay_ms * multiplier + proposed_delay_ms = ceiling_for_delay_ms // 2 + random.randrange(ceiling_for_delay_ms // 2 + 1) + return min(proposed_delay_ms, max_delay_ms) + + +async def sleep_before_try( + tries: int, + base_delay_ms: int = DEFAULT_BASE_DELAY_MS, + max_delay_ms: int = DEFAULT_MAX_DELAY_MS +): + await asyncio.sleep(delay_ms_for_try(tries, base_delay_ms, max_delay_ms) / 1000.0) + + +def sync_sleep_before_try( + tries: int, + base_delay_ms: int = DEFAULT_BASE_DELAY_MS, + max_delay_ms: int = DEFAULT_MAX_DELAY_MS +): + time.sleep(delay_ms_for_try(tries, base_delay_ms, max_delay_ms) / 1000.0) def retry_all_errors(msg=None, error_logging_interval=10): async def _wrapper(f, *args, **kwargs): - delay = 0.1 - errors = 0 + tries = 0 while True: try: return await f(*args, **kwargs) @@ -747,17 +767,16 @@ async def _wrapper(f, *args, **kwargs): except KeyboardInterrupt: raise except Exception: - errors += 1 - if msg and errors % error_logging_interval == 0: + tries += 1 + if msg and tries % error_logging_interval == 0: log.exception(msg, stack_info=True) - delay = await sleep_and_backoff(delay) + await sleep_before_try(tries) return _wrapper def retry_all_errors_n_times(max_errors=10, msg=None, error_logging_interval=10): async def _wrapper(f, *args, **kwargs): - delay = 0.1 - errors = 0 + tries = 0 while True: try: return await f(*args, **kwargs) @@ -766,12 +785,12 @@ async def _wrapper(f, *args, **kwargs): except KeyboardInterrupt: raise except Exception: - errors += 1 - if msg and errors % error_logging_interval == 0: + tries += 1 + if msg and tries % error_logging_interval == 0: log.exception(msg, stack_info=True) - if errors >= max_errors: + if tries >= max_errors: raise - delay = await sleep_and_backoff(delay) + await sleep_before_try(tries) return _wrapper @@ -785,70 +804,68 @@ async def retry_transient_errors_with_delayed_warnings(warning_delay_msecs: int, async def retry_transient_errors_with_debug_string(debug_string: str, warning_delay_msecs: int, f: Callable[..., Awaitable[T]], *args, **kwargs) -> T: start_time = time_msecs() - delay = 0.1 - errors = 0 + tries = 0 while True: try: return await f(*args, **kwargs) except KeyboardInterrupt: raise except Exception as e: - errors += 1 - if errors <= 5 and is_limited_retries_error(e): + tries += 1 + delay = delay_ms_for_try(tries) / 1000.0 + if tries <= 5 and is_limited_retries_error(e): log.warning( f'A limited retry error has occured. We will automatically retry ' - f'{5 - errors} more times. Do not be alarmed. (current delay: ' - f'{delay}). The most recent error was {type(e)} {e}. {debug_string}' + f'{5 - tries} more times. Do not be alarmed. (next delay: ' + f'{delay}s). The most recent error was {type(e)} {e}. {debug_string}' ) elif not is_transient_error(e): raise else: log_warnings = (time_msecs() - start_time >= warning_delay_msecs) or not is_delayed_warning_error(e) - if log_warnings and errors == 2: + if log_warnings and tries == 2: log.warning(f'A transient error occured. We will automatically retry. Do not be alarmed. ' - f'We have thus far seen {errors} transient errors (current delay: ' - f'{delay}). The most recent error was {type(e)} {e}. {debug_string}') - elif log_warnings and errors % 10 == 0: + f'We have thus far seen {tries} transient errors (next delay: ' + f'{delay}s). The most recent error was {type(e)} {e}. {debug_string}') + elif log_warnings and tries % 10 == 0: st = ''.join(traceback.format_stack()) log.warning(f'A transient error occured. We will automatically retry. ' - f'We have thus far seen {errors} transient errors (current delay: ' - f'{delay}). The stack trace for this call is {st}. The most recent error was {type(e)} {e}. {debug_string}', exc_info=True) - delay = await sleep_and_backoff(delay) + f'We have thus far seen {tries} transient errors (next delay: ' + f'{delay}s). The stack trace for this call is {st}. The most recent error was {type(e)} {e}. {debug_string}', exc_info=True) + await asyncio.sleep(delay) def sync_retry_transient_errors(f, *args, **kwargs): - delay = 0.1 - errors = 0 + tries = 0 while True: try: return f(*args, **kwargs) except KeyboardInterrupt: raise except Exception as e: - errors += 1 - if errors % 10 == 0: + tries += 1 + if tries % 10 == 0: st = ''.join(traceback.format_stack()) - log.warning(f'Encountered {errors} errors. My stack trace is {st}. Most recent error was {e}', exc_info=True) + log.warning(f'Encountered {tries} errors. My stack trace is {st}. Most recent error was {e}', exc_info=True) if is_transient_error(e): pass else: raise - delay = sync_sleep_and_backoff(delay) + sync_sleep_before_try(tries) def retry_response_returning_functions(fun, *args, **kwargs): - delay = 0.1 - errors = 0 + tries = 0 response = sync_retry_transient_errors( fun, *args, **kwargs) while response.status_code in RETRYABLE_HTTP_STATUS_CODES: - errors += 1 - if errors % 10 == 0: - log.warning(f'encountered {errors} bad status codes, most recent ' + tries += 1 + if tries % 10 == 0: + log.warning(f'encountered {tries} bad status codes, most recent ' f'one was {response.status_code}') response = sync_retry_transient_errors( fun, *args, **kwargs) - delay = sync_sleep_and_backoff(delay) + sync_sleep_before_try(tries) return response diff --git a/hail/python/test/hailtop/batch/test_batch_pool_executor.py b/hail/python/test/hailtop/batch/test_batch_pool_executor.py index 901b4cc2cc4..f4ab6cb38b9 100644 --- a/hail/python/test/hailtop/batch/test_batch_pool_executor.py +++ b/hail/python/test/hailtop/batch/test_batch_pool_executor.py @@ -5,7 +5,7 @@ from hailtop.batch import BatchPoolExecutor, ServiceBackend from hailtop.config import get_user_config -from hailtop.utils import sync_sleep_and_backoff +from hailtop.utils import sync_sleep_before_try from hailtop.batch_client.client import BatchClient PYTHON_DILL_IMAGE = 'hailgenetics/python-dill:3.8' @@ -33,12 +33,13 @@ def check_for_running_batches(): with BatchClient(billing_project=billing_project) as bc: for id in submitted_batch_ids: b = bc.get_batch(id) - delay = 0.1 + tries = 1 while True: if b.status()['state'] != 'running': break print(f'batch {b.id} is still running') - delay = sync_sleep_and_backoff(delay) + tries += 1 + sync_sleep_before_try(tries) def test_simple_map(backend): diff --git a/hail/src/main/scala/is/hail/services/package.scala b/hail/src/main/scala/is/hail/services/package.scala index 88cdc95b62b..6663fc55267 100644 --- a/hail/src/main/scala/is/hail/services/package.scala +++ b/hail/src/main/scala/is/hail/services/package.scala @@ -30,10 +30,30 @@ package object services { s } - def sleepAndBackoff(delay: Double): Double = { - val t = delay * Random.nextDouble() - Thread.sleep((t * 1000).toInt) // in ms - math.min(delay * 2, 60.0) + private[this] val LOG_2_MAX_MULTIPLIER = 30 // do not set larger than 30 due to integer overflow calculating multiplier + private[this] val DEFAULT_MAX_DELAY_MS = 60000 + private[this] val DEFAULT_BASE_DELAY_MS = 1000 + + def delayMsForTry( + tries: Int, + baseDelayMs: Int = DEFAULT_BASE_DELAY_MS, + maxDelayMs: Int = DEFAULT_MAX_DELAY_MS + ): Int = { + // Based on AWS' recommendations: + // - https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ + // - https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedBackoffStrategies.java + val multiplier = 1 << math.min(tries, LOG_2_MAX_MULTIPLIER) + val ceilingForDelayMs = baseDelayMs * multiplier + val proposedDelayMs = ceilingForDelayMs / 2 + Random.nextInt(ceilingForDelayMs / 2 + 1) + return math.min(proposedDelayMs, maxDelayMs) + } + + def sleepBeforTry( + tries: Int, + baseDelayMs: Int = DEFAULT_BASE_DELAY_MS, + maxDelayMs: Int = DEFAULT_MAX_DELAY_MS + ) = { + Thread.sleep(delayMsForTry(tries, baseDelayMs, maxDelayMs)) } def isLimitedRetriesError(_e: Throwable): Boolean = { @@ -156,26 +176,26 @@ package object services { } def retryTransientErrors[T](f: => T, reset: Option[() => Unit] = None): T = { - var delay = 0.1 - var errors = 0 + var tries = 0 while (true) { try { return f } catch { case e: Exception => - errors += 1 - if (errors <= 5 && isLimitedRetriesError(e)) { + tries += 1 + val delay = delayMsForTry(tries) + if (tries <= 5 && isLimitedRetriesError(e)) { log.warn( s"A limited retry error has occured. We will automatically retry " + - s"${5 - errors} more times. Do not be alarmed. (current delay: " + + s"${5 - tries} more times. Do not be alarmed. (next delay: " + s"$delay). The most recent error was $e.") } else if (!isTransientError(e)) { throw e - } else if (errors % 10 == 0) { - log.warn(s"Encountered $errors transient errors, most recent one was $e.") + } else if (tries % 10 == 0) { + log.warn(s"Encountered $tries transient errors, most recent one was $e.") } + Thread.sleep(delay) } - delay = sleepAndBackoff(delay) reset.foreach(_()) } From ddcc8964d268150dee854c473f03eb4e72ca8c8e Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 1 Aug 2023 19:00:20 -0400 Subject: [PATCH 049/180] [memory] Remove unused memory service (#13352) The memory service has been unused since #12784. Even older clients should still work if we delete the memory service as the old code path falls back to blob storage if a request to the memory service fails. --- Makefile | 15 +- build.yaml | 100 +-------- .../hail/backend/service/ServiceBackend.scala | 4 +- .../is/hail/backend/service/Worker.scala | 2 +- .../scala/is/hail/io/fs/AzureStorageFS.scala | 8 - hail/src/main/scala/is/hail/io/fs/FS.scala | 6 +- .../scala/is/hail/io/fs/GoogleStorageFS.scala | 11 - .../is/hail/io/fs/ServiceCacheableFS.scala | 82 -------- .../services/memory_client/MemoryClient.scala | 128 ------------ memory/Dockerfile | 23 --- memory/Makefile | 12 -- memory/deployment.yaml | 140 ------------- memory/memory/__init__.py | 0 memory/memory/__main__.py | 8 - memory/memory/client.py | 62 ------ memory/memory/memory.py | 191 ------------------ memory/pinned-requirements.txt | 15 -- memory/requirements.txt | 4 - memory/service-account.yaml | 25 --- memory/setup.py | 12 -- memory/test/test_memory.py | 76 ------- tls/config.yaml | 4 - 22 files changed, 15 insertions(+), 913 deletions(-) delete mode 100644 hail/src/main/scala/is/hail/io/fs/ServiceCacheableFS.scala delete mode 100644 hail/src/main/scala/is/hail/services/memory_client/MemoryClient.scala delete mode 100644 memory/Dockerfile delete mode 100644 memory/Makefile delete mode 100644 memory/deployment.yaml delete mode 100644 memory/memory/__init__.py delete mode 100644 memory/memory/__main__.py delete mode 100644 memory/memory/client.py delete mode 100644 memory/memory/memory.py delete mode 100644 memory/pinned-requirements.txt delete mode 100644 memory/requirements.txt delete mode 100644 memory/service-account.yaml delete mode 100644 memory/setup.py delete mode 100644 memory/test/test_memory.py diff --git a/Makefile b/Makefile index 780d46fab25..7b8aaaab905 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ include config.mk -SERVICES := auth batch ci memory notebook monitoring website +SERVICES := auth batch ci notebook monitoring website SERVICES_PLUS_ADMIN_POD := $(SERVICES) admin-pod SERVICES_IMAGES := $(patsubst %, %-image, $(SERVICES_PLUS_ADMIN_POD)) SERVICES_MODULES := $(SERVICES) gear web_common @@ -78,8 +78,7 @@ check-pip-requirements: web_common \ auth \ batch \ - ci \ - memory + ci .PHONY: check-linux-pip-requirements check-linux-pip-requirements: @@ -91,8 +90,7 @@ check-linux-pip-requirements: web_common \ auth \ batch \ - ci \ - memory + ci .PHONY: install-dev-requirements install-dev-requirements: @@ -103,8 +101,7 @@ install-dev-requirements: -r web_common/pinned-requirements.txt \ -r auth/pinned-requirements.txt \ -r batch/pinned-requirements.txt \ - -r ci/pinned-requirements.txt \ - -r memory/pinned-requirements.txt \ + -r ci/pinned-requirements.txt hail/python/hailtop/pinned-requirements.txt: hail/python/hailtop/requirements.txt ./generate-linux-pip-lockfile.sh hail/python/hailtop @@ -130,9 +127,6 @@ batch/pinned-requirements.txt: web_common/pinned-requirements.txt batch/requirem ci/pinned-requirements.txt: web_common/pinned-requirements.txt ci/requirements.txt ./generate-linux-pip-lockfile.sh ci -memory/pinned-requirements.txt: gear/pinned-requirements.txt memory/requirements.txt - ./generate-linux-pip-lockfile.sh memory - .PHONY: generate-pip-lockfiles generate-pip-lockfiles: hail/python/hailtop/pinned-requirements.txt generate-pip-lockfiles: hail/python/pinned-requirements.txt @@ -142,7 +136,6 @@ generate-pip-lockfiles: web_common/pinned-requirements.txt generate-pip-lockfiles: auth/pinned-requirements.txt generate-pip-lockfiles: batch/pinned-requirements.txt generate-pip-lockfiles: ci/pinned-requirements.txt -generate-pip-lockfiles: memory/pinned-requirements.txt $(HAILTOP_VERSION): $(MAKE) -C hail python/hailtop/hail_version diff --git a/build.yaml b/build.yaml index b3c838f3bc3..6089bd70eaf 100644 --- a/build.yaml +++ b/build.yaml @@ -176,8 +176,7 @@ steps: web_common \ auth \ batch \ - ci \ - memory + ci inputs: - from: /repo to: /io/repo @@ -890,34 +889,6 @@ steps: - merge_code - hail_ubuntu_image - jvm_entryway_jar - - kind: buildImage2 - name: memory_image - dockerFile: /io/repo/memory/Dockerfile - contextPath: /io/repo - publishAs: memory - inputs: - - from: /repo/memory - to: /io/repo/memory - - from: /repo/hail/python/setup-hailtop.py - to: /io/repo/hail/python/setup-hailtop.py - - from: /repo/hail/python/MANIFEST.in - to: /io/repo/hail/python/MANIFEST.in - - from: /repo/hail/python/hailtop - to: /io/repo/hail/python/hailtop - - from: /hail_version - to: /io/repo/hail/python/hailtop/hail_version - - from: /repo/gear - to: /io/repo/gear - dependsOn: - - hail_ubuntu_image - - merge_code - - kind: deploy - name: deploy_memory_sa - namespace: - valueFrom: default_ns.name - config: memory/service-account.yaml - dependsOn: - - default_ns - kind: runImage name: upload_test_resources_to_blob_storage image: @@ -982,6 +953,7 @@ steps: dependsOn: - default_ns - hail_run_image + - create_test_gsa_keys - build_hail_debug_jar_and_wheel - build_hail_test_artifacts - kind: buildImage2 @@ -1194,6 +1166,7 @@ steps: dependsOn: - default_ns - hail_run_image + - create_test_gsa_keys - build_hail_debug_jar_and_wheel - build_hail_test_artifacts clouds: @@ -1258,6 +1231,7 @@ steps: dependsOn: - default_ns - hailgenetics_hailtop_image + - create_test_gsa_keys - build_hail_test_artifacts clouds: - gcp @@ -1384,6 +1358,7 @@ steps: dependsOn: - default_ns - hail_run_image + - create_test_gsa_keys - build_hail_debug_jar_and_wheel - build_hail_test_artifacts - kind: runImage @@ -2454,20 +2429,6 @@ steps: - build_hail_jar_and_wheel - merge_code - create_test_gsa_keys - - kind: deploy - name: deploy_memory - namespace: - valueFrom: default_ns.name - config: memory/deployment.yaml - wait: - - kind: Service - name: memory - for: alive - dependsOn: - - default_ns - - memory_image - - deploy_memory_sa - - create_certs - kind: runImage name: test_hail_python_service_backend_gcp numSplits: 16 @@ -2546,7 +2507,6 @@ steps: - default_ns - merge_code - deploy_batch - - deploy_memory - create_deploy_config - create_accounts - hail_run_image @@ -2718,56 +2678,6 @@ steps: RUN hail-apt-get-install curl dependsOn: - hail_ubuntu_image - - kind: runImage - name: test_memory - resources: - memory: standard - cpu: '0.25' - image: - valueFrom: hail_dev_image.image - resources: - memory: 3.75Gi - cpu: '1' - script: | - export GOOGLE_APPLICATION_CREDENTIALS=/test-gsa-key/key.json - export AZURE_APPLICATION_CREDENTIALS=/test-gsa-key/key.json - hailctl config set batch/remote_tmpdir {{ global.test_storage_uri }}/test_memory/{{ token }}/ - - cd /io/memory - python3 -m pytest \ - -Werror:::hail -Werror:::hailtop -Werror::ResourceWarning \ - --log-cli-level=INFO \ - -s \ - -r A \ - -vv \ - --instafail \ - --durations=50 \ - --timeout=120 \ - test - timeout: 600 - secrets: - - name: worker-deploy-config - namespace: - valueFrom: default_ns.name - mountPath: /deploy-config - - name: test-tokens - namespace: - valueFrom: default_ns.name - mountPath: /user-tokens - - name: test-gsa-key - namespace: - valueFrom: default_ns.name - mountPath: /test-gsa-key - inputs: - - from: /repo/memory - to: /io/memory - dependsOn: - - create_deploy_config - - create_accounts - - default_ns - - merge_code - - hail_dev_image - - deploy_memory - kind: runImage name: test_batch numSplits: 5 diff --git a/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala b/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala index 7136ed7e534..2fc57f7265a 100644 --- a/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala +++ b/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala @@ -435,7 +435,7 @@ object ServiceBackendSocketAPI2 { val inputURL = argv(5) val outputURL = argv(6) - val fs = FS.cloudSpecificCacheableFS(s"$scratchDir/secrets/gsa-key/key.json", None) + val fs = FS.cloudSpecificFS(s"$scratchDir/secrets/gsa-key/key.json", None) val deployConfig = DeployConfig.fromConfigFile( s"$scratchDir/secrets/deploy-config/deploy-config.json") DeployConfig.set(deployConfig) @@ -666,7 +666,7 @@ class ServiceBackendSocketAPI2( ): () => Array[Byte] = { val flags = HailFeatureFlags.fromMap(flagsMap) val shouldProfile = flags.get("profile") != null - val fs = FS.cloudSpecificCacheableFS(s"${backend.scratchDir}/secrets/gsa-key/key.json", Some(flags)) + val fs = FS.cloudSpecificFS(s"${backend.scratchDir}/secrets/gsa-key/key.json", Some(flags)) { () => ExecutionTimer.logTime(methodName) { timer => diff --git a/hail/src/main/scala/is/hail/backend/service/Worker.scala b/hail/src/main/scala/is/hail/backend/service/Worker.scala index 596cb3013b8..23ec040fb4d 100644 --- a/hail/src/main/scala/is/hail/backend/service/Worker.scala +++ b/hail/src/main/scala/is/hail/backend/service/Worker.scala @@ -121,7 +121,7 @@ object Worker { timer.start(s"Job $i/$n") timer.start("readInputs") - val fs = FS.cloudSpecificCacheableFS(s"$scratchDir/secrets/gsa-key/key.json", None) + val fs = FS.cloudSpecificFS(s"$scratchDir/secrets/gsa-key/key.json", None) val (open, write) = ((x: String) => fs.openNoCompression(x), fs.writePDOS _) diff --git a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala index 3d47b2c3583..5f27a9d8774 100644 --- a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala @@ -433,12 +433,4 @@ class AzureStorageFS(val credentialsJSON: Option[String] = None) extends FS { AzureStorageFS.parseUrl(filename) filename } - - def asCacheable(): CacheableAzureStorageFS = new CacheableAzureStorageFS(credentialsJSON, null) -} - -class CacheableAzureStorageFS( - credentialsJSON: Option[String], - @transient val sessionID: String -) extends AzureStorageFS(credentialsJSON) with ServiceCacheableFS { } diff --git a/hail/src/main/scala/is/hail/io/fs/FS.scala b/hail/src/main/scala/is/hail/io/fs/FS.scala index 88287d7f11f..170918105a9 100644 --- a/hail/src/main/scala/is/hail/io/fs/FS.scala +++ b/hail/src/main/scala/is/hail/io/fs/FS.scala @@ -237,7 +237,7 @@ abstract class FSPositionedOutputStream(val capacity: Int) extends OutputStream } object FS { - def cloudSpecificCacheableFS( + def cloudSpecificFS( credentialsPath: String, flags: Option[HailFeatureFlags] ): FS = retryTransientErrors { @@ -250,9 +250,9 @@ object FS { flags.get("gcs_requester_pays_project"), flags.get("gcs_requester_pays_buckets") ) } - new GoogleStorageFS(credentialsStr, requesterPaysConfiguration).asCacheable() + new GoogleStorageFS(credentialsStr, requesterPaysConfiguration) case Some("azure") => - new AzureStorageFS(credentialsStr).asCacheable() + new AzureStorageFS(credentialsStr) case Some(cloud) => throw new IllegalArgumentException(s"Bad cloud: $cloud") case None => diff --git a/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala b/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala index 48423b62afa..6ad7ae5fc7d 100644 --- a/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala @@ -213,10 +213,6 @@ class GoogleStorageFS( } } - def asCacheable(): CacheableGoogleStorageFS = new CacheableGoogleStorageFS(serviceAccountKey, requesterPaysConfiguration, null) - - def asCacheable(sessionID: String): CacheableGoogleStorageFS = new CacheableGoogleStorageFS(serviceAccountKey, requesterPaysConfiguration, sessionID) - def openNoCompression(filename: String, _debug: Boolean = false): SeekableDataInputStream = retryTransientErrors { assert(!_debug) val url = parseUrl(filename) @@ -512,10 +508,3 @@ class GoogleStorageFS( filename } } - -class CacheableGoogleStorageFS( - serviceAccountKey: Option[String], - requesterPaysConfiguration: Option[RequesterPaysConfiguration] = None, - @transient val sessionID: String -) extends GoogleStorageFS(serviceAccountKey, requesterPaysConfiguration) with ServiceCacheableFS { -} diff --git a/hail/src/main/scala/is/hail/io/fs/ServiceCacheableFS.scala b/hail/src/main/scala/is/hail/io/fs/ServiceCacheableFS.scala deleted file mode 100644 index 3389adcbee4..00000000000 --- a/hail/src/main/scala/is/hail/io/fs/ServiceCacheableFS.scala +++ /dev/null @@ -1,82 +0,0 @@ -package is.hail.io.fs - -import java.io._ -import java.util.{concurrent => javaConcurrent} -import org.apache.commons.io.IOUtils -import org.apache.log4j.Logger -import scala.collection.mutable.ArrayBuffer -import scala.concurrent.duration.{Duration} -import scala.concurrent.{Future, Await, ExecutionContext} - -import is.hail.services.memory_client.MemoryClient -import is.hail.services.ClientResponseException -import is.hail.utils._ - -trait ServiceCacheableFS extends FS { - - private[this] implicit val ec = ExecutionContext.fromExecutorService( - javaConcurrent.Executors.newCachedThreadPool()) - - def sessionID: String - - private val log = Logger.getLogger(getClass.getName()) - - @transient lazy val client: MemoryClient = { - if (sessionID != null) - MemoryClient.fromSessionID(sessionID) - else MemoryClient.get - } - - override def openCachedNoCompression(filename: String): SeekableDataInputStream = { - client.open(filename).map(new WrappedSeekableDataInputStream(_)).getOrElse(openNoCompression(filename)) - } - - override def writeCached(filename: String)(writer: PositionedDataOutputStream => Unit) = { - try { - client.writeToStream(filename) { os => - writer(outputStreamToPositionedDataOutputStream(os)) - } - } catch { - case exc: Exception => - log.error(f"Unexpected failure $filename writing to memory. Retrying directly to GCS.", exc) - using(createNoCompression(filename))(writer) - } - } - - override def createCachedNoCompression(filename: String): PositionedDataOutputStream = { - val pis = new PipedInputStream() - val pos = new PipedOutputStream(pis) - val writerFuture = Future { - client.writeToStream(filename) { os => IOUtils.copy(pis, os) } - } - val os: PositionedOutputStream = new OutputStream with Positioned { - private[this] var count: Long = 0L - - override def flush(): Unit = { - pos.flush() - if (writerFuture.isCompleted) { - // there might be an exception, we should eagerly retrieve that and report it - Await.result(writerFuture, Duration.Inf) - } - } - - override def write(i: Int): Unit = { - pos.write(i) - count += 1 - } - - override def write(bytes: Array[Byte], off: Int, len: Int): Unit = { - pos.write(bytes, off, len) - } - - override def close(): Unit = { - pos.close() - Await.result(writerFuture, Duration.Inf) - } - - def getPosition: Long = count - } - - new WrappedPositionedDataOutputStream(os) - } -} diff --git a/hail/src/main/scala/is/hail/services/memory_client/MemoryClient.scala b/hail/src/main/scala/is/hail/services/memory_client/MemoryClient.scala deleted file mode 100644 index 36d9156363b..00000000000 --- a/hail/src/main/scala/is/hail/services/memory_client/MemoryClient.scala +++ /dev/null @@ -1,128 +0,0 @@ -package is.hail.services.memory_client - -import java.io._ - -import is.hail.HailContext -import is.hail.io.fs.{Seekable, Positioned} -import is.hail.services.{ClientResponseException, DeployConfig, Requester, Tokens} -import org.apache.http.client.methods._ -import org.apache.http.entity._ -import org.apache.http._ -import org.apache.http.client.utils.URIBuilder -import org.apache.log4j.{LogManager, Logger} -import org.json4s.JValue - -object MemoryClient { - private val log = Logger.getLogger(getClass.getName()) - - def fromSessionID(sessionID: String): MemoryClient = { - val deployConfig = DeployConfig.get - new MemoryClient(deployConfig, - new Tokens(Map( - deployConfig.getServiceNamespace("memory") -> sessionID))) - } - - def get: MemoryClient = new MemoryClient(DeployConfig.get, Tokens.get) -} - -class MemoryClient(val deployConfig: DeployConfig, tokens: Tokens) { - val requester = new Requester(tokens, "memory") - - import MemoryClient.log - import requester.request - - private[this] val baseUrl = deployConfig.baseUrl("memory") - - def open(path: String): Option[MemorySeekableInputStream] = - try { - Some(new MemorySeekableInputStream(requester, s"$baseUrl/api/v1alpha/objects", path)) - } catch { case e: ClientResponseException if e.status == 404 => - None - } - - def write(path: String, data: Array[Byte]): Unit = { - val uri = new URIBuilder(s"$baseUrl/api/v1alpha/objects").addParameter("q", path) - val req = new HttpPost(uri.build()) - requester.request(req, new ByteArrayEntity(data)) - } - - def writeToStream( - path: String, - _isRepeatable: Boolean = false, - _contentType: String = "application/octet-stream", - _contentLength: Long = -1, - _isChunked: Boolean = true - )( - writer: OutputStream => Unit - ): Unit = { - val uri = new URIBuilder(s"$baseUrl/api/v1alpha/objects").addParameter("q", path) - val req = new HttpPost(uri.build()) - val entity = new AbstractHttpEntity { - def isRepeatable(): Boolean = _isRepeatable - def writeTo(os: OutputStream): Unit = writer(os) - def getContentLength() = _contentLength - def getContent() = throw new UnsupportedOperationException() - def isStreaming() = true - } - entity.setContentType(_contentType) - entity.setChunked(_isChunked) - requester.request(req, entity) - } -} - -class MemorySeekableInputStream(requester: Requester, objectEndpoint: String, fileURI: String) extends InputStream with Seekable { - private[this] val uri = new URIBuilder(objectEndpoint) - .addParameter("q", fileURI) - - private[this] val req = new HttpGet(uri.build()) - - private[this] val _bytes = requester.requestAsByteStream(req) - private[this] var _pos: Int = 0 - private[this] val _len: Int = _bytes.length - - override def read(): Int = { - if (_pos >= _len) -1 else { - _pos += 1 - _bytes(_pos - 1).toInt & 0xff - } - } - - override def read(bytes: Array[Byte], off: Int, len: Int): Int = { - if (off < 0 || len < 0 || len > bytes.length - off) - throw new IndexOutOfBoundsException() - if (len == 0) - 0 - else if (_pos >= _len) - -1 - else { - val n_read: Int = java.lang.Math.min(_len - _pos, len) - System.arraycopy(_bytes, _pos, bytes, off, n_read) - _pos += n_read - n_read - } - } - - override def skip(n: Long): Long = { - if (n <= 0L) - 0L - else { - if (_pos + n >= _len) { - val r = _len - _pos - _pos = _len - r - } else { - _pos = _pos + n.toInt - n - } - } - } - - override def close(): Unit = {} - - def getPosition: Long = _pos - - def seek(pos: Long): Unit = - if (pos < 0 || pos > _len) - throw new IOException(s"Cannot seek to position $pos") - else _pos = pos.toInt -} diff --git a/memory/Dockerfile b/memory/Dockerfile deleted file mode 100644 index 5aca201f26a..00000000000 --- a/memory/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM {{ hail_ubuntu_image.image }} - -COPY hail/python/hailtop/pinned-requirements.txt hailtop-requirements.txt -COPY gear/pinned-requirements.txt gear-requirements.txt -COPY memory/pinned-requirements.txt memory-requirements.txt -RUN hail-pip-install \ - -r hailtop-requirements.txt \ - -r gear-requirements.txt \ - -r memory-requirements.txt - -COPY hail/python/setup-hailtop.py /hailtop/setup.py -COPY hail/python/MANIFEST.in /hailtop/MANIFEST.in -COPY hail/python/hailtop /hailtop/hailtop/ - -COPY gear/setup.py /gear/setup.py -COPY gear/gear /gear/gear/ - -COPY memory/setup.py /memory/ -COPY memory/memory /memory/memory/ - -RUN hail-pip-install /hailtop /gear /memory - -EXPOSE 5000 diff --git a/memory/Makefile b/memory/Makefile deleted file mode 100644 index 544ed8657f5..00000000000 --- a/memory/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include ../config.mk - -.PHONY: build -build: - $(MAKE) -C .. memory-image - -.PHONY: deploy -deploy: build - ! [ -z $(NAMESPACE) ] # call this like: make deploy NAMESPACE=default - kubectl -n $(NAMESPACE) apply -f service-account.yaml - python3 ../ci/jinja2_render.py '{"code":{"sha":"$(shell git rev-parse --short=12 HEAD)"},"deploy":$(DEPLOY),"memory_image":{"image":"'$$(cat ../memory-image)'"},"global":{"docker_prefix":"$(DOCKER_PREFIX)"},"default_ns":{"name":"$(NAMESPACE)"}}' deployment.yaml deployment.yaml.out - kubectl -n $(NAMESPACE) apply -f deployment.yaml.out diff --git a/memory/deployment.yaml b/memory/deployment.yaml deleted file mode 100644 index b3da29cac71..00000000000 --- a/memory/deployment.yaml +++ /dev/null @@ -1,140 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: memory - labels: - app: memory - hail.is/sha: "{{ code.sha }}" -spec: - selector: - matchLabels: - app: memory - replicas: 1 - template: - metadata: - labels: - app: memory - hail.is/sha: "{{ code.sha }}" - grafanak8sapp: "true" - annotations: - "cluster-autoscaler.kubernetes.io/safe-to-evict": "true" - spec: - serviceAccountName: memory -{% if deploy %} - priorityClassName: production -{% endif %} - containers: - - name: redis - image: {{ global.docker_prefix }}/redis:6.0.6-alpine - command: - - redis-server - - --port - - "0" - - --unixsocket - - /redis/redis.sock - - --timeout - - "0" - - --maxmemory - - 2gb - - --maxmemory-policy - - allkeys-lru - volumeMounts: - - name: redis-socket - mountPath: /redis - resources: - requests: - cpu: "10m" - memory: "1G" - limits: - cpu: "1" - memory: "2.5G" - readinessProbe: - exec: - command: - - redis-cli - - -s - - /redis/redis.sock - - ping - initialDelaySeconds: 5 - periodSeconds: 5 - - name: memory - image: "{{ memory_image.image }}" - command: -{% if not deploy %} - - /controller.sh -{% endif %} - - python3 - - -m - - memory - env: - - name: HAIL_DOMAIN - valueFrom: - secretKeyRef: - name: global-config - key: domain - - name: HAIL_DEPLOY_CONFIG_FILE - value: /deploy-config/deploy-config.json - - name: HAIL_DEFAULT_NAMESPACE - value: "{{ default_ns.name }}" - - name: HAIL_SHA - value: "{{ code.sha }}" - ports: - - containerPort: 5000 - volumeMounts: - - name: redis-socket - mountPath: /redis - - name: deploy-config - mountPath: /deploy-config - readOnly: true - - name: session-secret-key - mountPath: /session-secret-key - readOnly: true - - name: ssl-config - mountPath: /ssl-config - readOnly: true - - mountPath: /global-config - name: global-config - readOnly: true - resources: - requests: - memory: "500M" - cpu: "100m" - limits: - memory: "3.75G" - cpu: "1" - readinessProbe: - tcpSocket: - port: 5000 - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: redis-socket - emptyDir: {} - - name: deploy-config - secret: - secretName: deploy-config - - name: session-secret-key - secret: - secretName: session-secret-key - - name: ssl-config - secret: - optional: false - secretName: ssl-config-memory - - name: global-config - secret: - secretName: global-config ---- -apiVersion: v1 -kind: Service -metadata: - name: memory - labels: - app: memory -spec: - ports: - - name: memory - port: 443 - protocol: TCP - targetPort: 5000 - selector: - app: memory diff --git a/memory/memory/__init__.py b/memory/memory/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/memory/memory/__main__.py b/memory/memory/__main__.py deleted file mode 100644 index 0779493ff0e..00000000000 --- a/memory/memory/__main__.py +++ /dev/null @@ -1,8 +0,0 @@ -from hailtop.hail_logging import configure_logging - -# configure logging before importing anything else -configure_logging() - -from .memory import run # noqa: E402 pylint: disable=wrong-import-position - -run() diff --git a/memory/memory/client.py b/memory/memory/client.py deleted file mode 100644 index ef8f1fe7159..00000000000 --- a/memory/memory/client.py +++ /dev/null @@ -1,62 +0,0 @@ -import aiohttp - -from hailtop.aiocloud.aiogoogle import GoogleStorageAsyncFS -from hailtop.auth import hail_credentials -from hailtop.config import get_deploy_config -from hailtop.httpx import client_session -from hailtop.utils import retry_transient_errors - - -class MemoryClient: - def __init__(self, gcs_project=None, fs=None, deploy_config=None, session=None, headers=None): - if not deploy_config: - self._deploy_config = get_deploy_config() - else: - self._deploy_config = deploy_config - - self.url = self._deploy_config.base_url('memory') - self.objects_url = f'{self.url}/api/v1alpha/objects' - self._session = session - - if fs is None: - fs = GoogleStorageAsyncFS(project=gcs_project) - self._fs = fs - - self._headers = {} - if headers: - self._headers.update(headers) - - async def async_init(self): - if self._session is None: - self._session = client_session() - self._headers.update(await hail_credentials().auth_headers()) - - async def _get_file_if_exists(self, filename): - params = {'q': filename} - try: - return await retry_transient_errors( - self._session.get_read, self.objects_url, params=params, headers=self._headers - ) - except aiohttp.ClientResponseError as e: - if e.status == 404: - return None - raise e - - async def read_file(self, filename): - data = await self._get_file_if_exists(filename) - if data is not None: - return data - return await self._fs.read(filename) - - async def write_file(self, filename, data): - params = {'q': filename} - response = await retry_transient_errors( - self._session.post, self.objects_url, params=params, headers=self._headers, data=data - ) - assert response.status == 200 - - async def close(self): - await self._session.close() - self._session = None - await self._fs.close() - self._fs = None diff --git a/memory/memory/memory.py b/memory/memory/memory.py deleted file mode 100644 index 85b9fa264a5..00000000000 --- a/memory/memory/memory.py +++ /dev/null @@ -1,191 +0,0 @@ -import asyncio -import base64 -import json -import logging -import os -import signal -from collections import defaultdict - -import aioredis -import kubernetes_asyncio.client -import kubernetes_asyncio.config -import uvloop -from aiohttp import web -from prometheus_async.aio.web import server_stats # type: ignore - -from gear import AuthClient, monitor_endpoints_middleware, setup_aiohttp_session -from gear.clients import get_cloud_async_fs_factory -from hailtop import httpx -from hailtop.aiotools import AsyncFS -from hailtop.config import get_deploy_config -from hailtop.hail_logging import AccessLogger -from hailtop.tls import internal_server_ssl_context -from hailtop.utils import dump_all_stacktraces, retry_transient_errors - -uvloop.install() - -DEFAULT_NAMESPACE = os.environ['HAIL_DEFAULT_NAMESPACE'] -log = logging.getLogger('memory') -routes = web.RouteTableDef() - -socket = '/redis/redis.sock' - -ASYNC_FS_FACTORY = get_cloud_async_fs_factory() - -auth = AuthClient() - - -@routes.get('/healthcheck') -async def healthcheck(request): # pylint: disable=unused-argument - return web.Response() - - -@routes.get('/api/v1alpha/objects') -@auth.rest_authenticated_users_only -async def get_object(request, userdata): - filepath = request.query.get('q') - userinfo = await get_or_add_user(request.app, userdata) - username = userdata['username'] - maybe_file = await get_file_or_none(request.app, username, userinfo['fs'], filepath) - if maybe_file is None: - raise web.HTTPNotFound() - return web.Response(body=maybe_file) - - -@routes.post('/api/v1alpha/objects') -@auth.rest_authenticated_users_only -async def write_object(request, userdata): - filepath = request.query.get('q') - userinfo = await get_or_add_user(request.app, userdata) - username = userdata['username'] - data = await request.read() - - file_key = make_redis_key(username, filepath) - - async def persist_and_cache(): - try: - await persist(userinfo['fs'], filepath, data) - await cache_file(request.app['redis_pool'], file_key, data) - return data - finally: - del request.app['files_in_progress'][file_key] - - fut = asyncio.ensure_future(persist_and_cache()) - request.app['files_in_progress'][file_key] = fut - await fut - return web.Response(status=200) - - -async def get_or_add_user(app, userdata): - users = app['users'] - userlocks = app['userlocks'] - username = userdata['username'] - if username not in users: - async with userlocks[username]: - if username not in users: - k8s_client = app['k8s_client'] - hail_credentials_secret = await retry_transient_errors( - k8s_client.read_namespaced_secret, - userdata['hail_credentials_secret_name'], - DEFAULT_NAMESPACE, - _request_timeout=5.0, - ) - cloud_credentials_data = json.loads(base64.b64decode(hail_credentials_secret.data['key.json']).decode()) - users[username] = {'fs': ASYNC_FS_FACTORY.from_credentials_data(cloud_credentials_data)} - return users[username] - - -def make_redis_key(username, filepath): - return f'{ username }_{ filepath }' - - -async def get_file_or_none(app, username, fs: AsyncFS, filepath): - file_key = make_redis_key(username, filepath) - redis_pool: aioredis.ConnectionsPool = app['redis_pool'] - - (body,) = await redis_pool.execute('HMGET', file_key, 'body') - if body is not None: - return body - - if file_key in app['files_in_progress']: - return await app['files_in_progress'][file_key] - - async def load_and_cache(): - try: - data = await load_file(fs, filepath) - await cache_file(redis_pool, file_key, data) - return data - except FileNotFoundError: - return None - finally: - del app['files_in_progress'][file_key] - - fut = asyncio.ensure_future(load_and_cache()) - app['files_in_progress'][file_key] = fut - return await fut - - -async def load_file(fs: AsyncFS, filepath): - data = await fs.read(filepath) - return data - - -async def persist(fs: AsyncFS, filepath: str, data: bytes): - await fs.write(filepath, data) - - -async def cache_file(redis: aioredis.ConnectionsPool, file_key: str, data: bytes): - await redis.execute('HMSET', file_key, 'body', data) - - -async def on_startup(app): - app['client_session'] = httpx.client_session() - app['files_in_progress'] = {} - app['users'] = {} - app['userlocks'] = defaultdict(asyncio.Lock) - kubernetes_asyncio.config.load_incluster_config() - k8s_client = kubernetes_asyncio.client.CoreV1Api() - app['k8s_client'] = k8s_client - app['redis_pool'] = await aioredis.create_pool(socket) - - -async def on_cleanup(app): - try: - app['redis_pool'].close() - finally: - try: - del app['k8s_client'] - finally: - try: - await app['client_session'].close() - finally: - try: - for items in app['users'].values(): - try: - await items['fs'].close() - except: - pass - finally: - await asyncio.gather(*(t for t in asyncio.all_tasks() if t is not asyncio.current_task())) - - -def run(): - app = web.Application(middlewares=[monitor_endpoints_middleware]) - - setup_aiohttp_session(app) - app.add_routes(routes) - app.router.add_get("/metrics", server_stats) - - app.on_startup.append(on_startup) - app.on_cleanup.append(on_cleanup) - - asyncio.get_event_loop().add_signal_handler(signal.SIGUSR1, dump_all_stacktraces) - - deploy_config = get_deploy_config() - web.run_app( - deploy_config.prefix_application(app, 'memory'), - host='0.0.0.0', - port=5000, - access_log_class=AccessLogger, - ssl_context=internal_server_ssl_context(), - ) diff --git a/memory/pinned-requirements.txt b/memory/pinned-requirements.txt deleted file mode 100644 index d49b48ad085..00000000000 --- a/memory/pinned-requirements.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# pip-compile --output-file=hail/memory/pinned-requirements.txt hail/memory/requirements.txt -# -aioredis==1.3.1 - # via -r hail/memory/requirements.txt -async-timeout==4.0.2 - # via - # -c hail/memory/../gear/pinned-requirements.txt - # -c hail/memory/../hail/python/pinned-requirements.txt - # aioredis -hiredis==2.2.3 - # via aioredis diff --git a/memory/requirements.txt b/memory/requirements.txt deleted file mode 100644 index 61c717dc95a..00000000000 --- a/memory/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ --c ../hail/python/pinned-requirements.txt --c ../hail/python/dev/pinned-requirements.txt --c ../gear/pinned-requirements.txt -aioredis>=1.3.1,<2 diff --git a/memory/service-account.yaml b/memory/service-account.yaml deleted file mode 100644 index 30d9ba23b79..00000000000 --- a/memory/service-account.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: memory ---- -kind: Role -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: memory -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "list"] ---- -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: memory -subjects: -- kind: ServiceAccount - name: memory -roleRef: - kind: Role - name: memory - apiGroup: rbac.authorization.k8s.io diff --git a/memory/setup.py b/memory/setup.py deleted file mode 100644 index 47b92e5160e..00000000000 --- a/memory/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -from setuptools import find_packages, setup - -setup( - name='memory', - version='0.0.2', - url='https://github.com/hail-is/hail.git', - author='Hail Team', - author_email='hail@broadinstitute.org', - description='Caching service', - packages=find_packages(), - include_package_data=True, -) diff --git a/memory/test/test_memory.py b/memory/test/test_memory.py deleted file mode 100644 index 82ca4a4ef5e..00000000000 --- a/memory/test/test_memory.py +++ /dev/null @@ -1,76 +0,0 @@ -import unittest -import uuid - -from hailtop.aiotools.router_fs import RouterAsyncFS -from hailtop.config import get_user_config -from hailtop.utils import async_to_blocking -from memory.client import MemoryClient - - -class BlockingMemoryClient: - def __init__(self, gcs_project=None, fs=None, deploy_config=None, session=None, headers=None): - self._client = MemoryClient(gcs_project, fs, deploy_config, session, headers) - async_to_blocking(self._client.async_init()) - - def _get_file_if_exists(self, filename): - return async_to_blocking(self._client._get_file_if_exists(filename)) - - def read_file(self, filename): - return async_to_blocking(self._client.read_file(filename)) - - def write_file(self, filename, data): - return async_to_blocking(self._client.write_file(filename, data)) - - def close(self): - return async_to_blocking(self._client.close()) - - -class Tests(unittest.TestCase): - def setUp(self): - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') - token = uuid.uuid4() - self.test_path = f'{remote_tmpdir}memory-tests/{token}' - self.fs = RouterAsyncFS() - self.client = BlockingMemoryClient(fs=self.fs) - self.temp_files = set() - - def tearDown(self): - async_to_blocking(self.fs.rmtree(None, self.test_path)) - self.client.close() - - async def add_temp_file_from_string(self, name: str, str_value: bytes): - handle = f'{self.test_path}/{name}' - - async with await self.fs.create(handle) as f: - await f.write(str_value) - - return handle - - def test_non_existent(self): - for _ in range(3): - self.assertIsNone(self.client._get_file_if_exists(f'{self.test_path}/nonexistent')) - - def test_small_write_around(self): - async def read(url): - async with await self.fs.open(url) as f: - return await f.read() - - cases = [('empty_file', b''), ('null', b'\0'), ('small', b'hello world')] - for file, data in cases: - handle = async_to_blocking(self.add_temp_file_from_string(file, data)) - expected = async_to_blocking(read(handle)) - self.assertEqual(expected, data) - i = 0 - cached = self.client._get_file_if_exists(handle) - while cached is None and i < 10: - cached = self.client._get_file_if_exists(handle) - i += 1 - self.assertEqual(cached, expected) - - def test_small_write_through(self): - cases = [('empty_file2', b''), ('null2', b'\0'), ('small2', b'hello world')] - for file, data in cases: - filename = f'{self.test_path}/{file}' - self.client.write_file(filename, data) - cached = self.client._get_file_if_exists(filename) - self.assertEqual(cached, data) diff --git a/tls/config.yaml b/tls/config.yaml index 0d8f751231a..7bf409de936 100644 --- a/tls/config.yaml +++ b/tls/config.yaml @@ -56,10 +56,6 @@ principals: - internal-gateway unmanged: True kind: nginx -- name: memory - domains: - - memory - kind: json - name: monitoring domains: - monitoring From 5d29f89482c4c9dae554e433f4a5ca7c40ecafb3 Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Tue, 1 Aug 2023 21:44:26 -0400 Subject: [PATCH 050/180] [compiler] incremental hashing based on Threefry (#13317) --- .../main/scala/is/hail/expr/ir/Random.scala | 69 +++++++++++++++++-- .../scala/is/hail/expr/ir/RandomSuite.scala | 13 ++++ 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/hail/src/main/scala/is/hail/expr/ir/Random.scala b/hail/src/main/scala/is/hail/expr/ir/Random.scala index b4ec50be458..4d4fb9dd04f 100644 --- a/hail/src/main/scala/is/hail/expr/ir/Random.scala +++ b/hail/src/main/scala/is/hail/expr/ir/Random.scala @@ -220,13 +220,30 @@ object Threefry { cb.println(s"[$info]=\n\t", x(0).toString, " ", x(1).toString, " ", x(2).toString, " ", x(3).toString) } - def pmac(nonce: Long, staticID: Long, message: IndexedSeq[Long]): Array[Long] = { - val (hash, finalTweak) = pmacHash(nonce, staticID, message) + def pmac(sum: Array[Long], message: IndexedSeq[Long]): Array[Long] = { + val (hash, finalTweak) = pmacHashFromState(sum, message) encrypt(Threefry.defaultKey, Array(finalTweak, 0L), hash) hash } - def pmacHash(nonce: Long, staticID: Long, _message: IndexedSeq[Long]): (Array[Long], Long) = { + def pmac(nonce: Long, staticID: Long, message: IndexedSeq[Long]): Array[Long] = { + val sum = Array(nonce, staticID, 0L, 0L) + encrypt(Threefry.defaultKey, Array(Threefry.staticTweak, 0L), sum) + pmac(sum, message) + } + + def pmac(message: IndexedSeq[Long]): Array[Long] = { + val sum = Array.ofDim[Long](4) + pmac(sum, message) + } + + def pmacHash(nonce: Long, staticID: Long, message: IndexedSeq[Long]): (Array[Long], Long) = { + val sum = Array(nonce, staticID, 0L, 0L) + encrypt(Threefry.defaultKey, Array(Threefry.staticTweak, 0L), sum) + pmacHashFromState(sum, message) + } + + def pmacHashFromState(sum: Array[Long], _message: IndexedSeq[Long]): (Array[Long], Long) = { val length = _message.length val paddedLength = Math.max((length + 3) & (~3), 4) val padded = (paddedLength != length) @@ -234,8 +251,6 @@ object Threefry { _message.copyToArray(message) if (padded) message(length) = 1L - val sum = Array(nonce, staticID, 0L, 0L) - encrypt(Threefry.defaultKey, Array(Threefry.staticTweak, 0L), sum) var i = 0 while (i + 4 < paddedLength) { val x = message.slice(i, i + 4) @@ -269,6 +284,50 @@ object Threefry { } } +class PMacHash() { + val sum = Array.ofDim[Long](4) + var i = 0 + val buffer = Array.ofDim[Long](4) + var curOffset = 0 + + def extend(a: Array[Long]): PMacHash = { + val n = a.length + var j = 0 + while (4 - curOffset < n - j) { + val lenCopied = 4 - curOffset + Array.copy(a, j, buffer, curOffset, lenCopied) + Threefry.encrypt(Threefry.defaultKey, Array(i.toLong, 0L), buffer) + sum(0) ^= buffer(0) + sum(1) ^= buffer(1) + sum(2) ^= buffer(2) + sum(3) ^= buffer(3) + curOffset = 0 + j += lenCopied + i += 1 + } + Array.copy(a, j, buffer, curOffset, n - j) + curOffset += n - j + this + } + + def hash: Array[Long] = { + assert(i == 0 || curOffset > 0) + val finalTweak = if (curOffset < 4) { + buffer(curOffset) = 1 + curOffset += 1 + Threefry.finalBlockPaddedTweak + } else + Threefry.finalBlockNoPadTweak + var j = 0 + while (j < curOffset) { + sum(j) ^= buffer(j) + j += 1 + } + Threefry.encrypt(Threefry.defaultKey, Array(finalTweak, 0L), sum) + sum + } +} + object ThreefryRandomEngine { def apply(): ThreefryRandomEngine = { val key = Threefry.defaultKey diff --git a/hail/src/test/scala/is/hail/expr/ir/RandomSuite.scala b/hail/src/test/scala/is/hail/expr/ir/RandomSuite.scala index b0b5d8ca0ee..f8d3a5a4e9c 100644 --- a/hail/src/test/scala/is/hail/expr/ir/RandomSuite.scala +++ b/hail/src/test/scala/is/hail/expr/ir/RandomSuite.scala @@ -150,6 +150,19 @@ class RandomSuite extends HailSuite { } } + @Test def testPMACHash() { + for { + (message, _) <- pmacTestCases + } { + val res1 = Threefry.pmac(message) + val res2 = new PMacHash().extend(message).hash + val n = message.length + val res3 = new PMacHash().extend(message.slice(0, n / 2)).extend(message.slice(n / 2, n)).hash + assert(res1 sameElements res2) + assert(res1 sameElements res3) + } + } + @Test def testRandomEngine() { for { (message, staticID) <- pmacTestCases From 3fb7e0528383881e40563a6ef8a61fddccc16422 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Tue, 1 Aug 2023 22:56:24 -0400 Subject: [PATCH 051/180] [query] Fix copy_log when log path is relative. (#13340) the local_path_uri function simply prepends 'file://' to the path provided. This leads to an odd situation were a relative path is transformed into 'file://relative/path/to/log', which parses as: SCHEME: file HOST : relative PATH : path/to/log To fix this, compute the real path of the log file and use that as the path for the local_path_uri --- hail/python/hail/utils/hadoop_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hail/python/hail/utils/hadoop_utils.py b/hail/python/hail/utils/hadoop_utils.py index 4127d294e22..f87203d5a2e 100644 --- a/hail/python/hail/utils/hadoop_utils.py +++ b/hail/python/hail/utils/hadoop_utils.py @@ -287,12 +287,12 @@ def copy_log(path: str) -> None: ---------- path: :class:`str` """ - log = Env.hc()._log + log = os.path.realpath(Env.hc()._log) try: if hadoop_is_dir(path): _, tail = os.path.split(log) path = os.path.join(path, tail) info(f"copying log to {repr(path)}...") - hadoop_copy(local_path_uri(Env.hc()._log), path) + hadoop_copy(local_path_uri(log), path) except Exception as e: sys.stderr.write(f'Could not copy log: encountered error:\n {e}') From d83d9c71b62fc225e48eea0217ab28750926898a Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Wed, 2 Aug 2023 00:06:49 -0400 Subject: [PATCH 052/180] [query/vds] fix transform_gvcf docs (#13341) It returns a VariantDataset not a Table --- hail/python/hail/vds/combiner/combine.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hail/python/hail/vds/combiner/combine.py b/hail/python/hail/vds/combiner/combine.py index 857ac22ae77..0deeafea3f0 100644 --- a/hail/python/hail/vds/combiner/combine.py +++ b/hail/python/hail/vds/combiner/combine.py @@ -300,8 +300,8 @@ def transform_gvcf(mt: MatrixTable, Returns ------- - :obj:`.Table` - A localized matrix table that can be used as part of the input to `combine_gvcfs` + :obj:`.VariantDataset` + A single sample variant dataset Notes ----- From 8e300173f7193e054830ddcba9cac73c4e7d192d Mon Sep 17 00:00:00 2001 From: iris <84595986+iris-garden@users.noreply.github.com> Date: Wed, 2 Aug 2023 01:26:18 -0400 Subject: [PATCH 053/180] [deps] removes dependency on hurry.filesize (#13255) --- hail/python/dev/pinned-requirements.txt | 26 ++++++++++--------- hail/python/hailtop/fs/stat_result.py | 4 +-- hail/python/hailtop/utils/filesize.py | 17 ++++++++++++ hail/python/pinned-requirements.txt | 5 ---- hail/python/requirements.txt | 1 - .../test/hailtop/utils/test_filesize.py | 25 ++++++++++++++++++ 6 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 hail/python/hailtop/utils/filesize.py create mode 100644 hail/python/test/hailtop/utils/test_filesize.py diff --git a/hail/python/dev/pinned-requirements.txt b/hail/python/dev/pinned-requirements.txt index 23bad8ad78a..4e8d891420e 100644 --- a/hail/python/dev/pinned-requirements.txt +++ b/hail/python/dev/pinned-requirements.txt @@ -18,7 +18,7 @@ astroid==2.15.6 # via pylint asttokens==2.2.1 # via stack-data -async-lru==2.0.3 +async-lru==2.0.4 # via jupyterlab attrs==23.1.0 # via @@ -57,7 +57,9 @@ click==8.1.6 # black # curlylint comm==0.1.3 - # via ipykernel + # via + # ipykernel + # ipywidgets contourpy==1.1.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt @@ -126,7 +128,6 @@ iniconfig==2.0.0 # via pytest ipykernel==6.25.0 # via - # ipywidgets # jupyter # jupyter-console # jupyterlab @@ -138,13 +139,13 @@ ipython==8.12.2 # jupyter-console ipython-genutils==0.2.0 # via qtconsole -ipywidgets==8.0.7 +ipywidgets==8.1.0 # via jupyter isoduration==20.11.0 # via jsonschema isort==5.12.0 # via pylint -jedi==0.18.2 +jedi==0.19.0 # via ipython jinja2==3.1.2 # via @@ -188,7 +189,7 @@ jupyter-core==5.3.1 # nbconvert # nbformat # qtconsole -jupyter-events==0.6.3 +jupyter-events==0.7.0 # via jupyter-server jupyter-lsp==2.2.0 # via jupyterlab @@ -243,7 +244,7 @@ nbconvert==7.7.3 # jupyter # jupyter-server # nbsphinx -nbformat==5.9.1 +nbformat==5.9.2 # via # jupyter-server # nbclient @@ -255,7 +256,7 @@ nest-asyncio==1.5.6 # via # -c hail/hail/python/dev/../pinned-requirements.txt # ipykernel -notebook==7.0.0 +notebook==7.0.1 # via jupyter notebook-shim==0.2.3 # via @@ -287,7 +288,7 @@ parso==0.8.3 # via jedi parsy==1.1.0 # via curlylint -pathspec==0.11.1 +pathspec==0.11.2 # via # black # curlylint @@ -301,7 +302,7 @@ pillow==10.0.0 # matplotlib pkgutil-resolve-name==1.3.10 # via jsonschema -platformdirs==3.9.1 +platformdirs==3.10.0 # via # black # jupyter-core @@ -398,6 +399,7 @@ referencing==0.30.0 # via # jsonschema # jsonschema-specifications + # jupyter-events requests==2.31.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt @@ -415,7 +417,7 @@ rpds-py==0.9.2 # via # jsonschema # referencing -ruff==0.0.280 +ruff==0.0.282 # via -r hail/hail/python/dev/requirements.txt send2trash==1.8.2 # via jupyter-server @@ -477,7 +479,7 @@ tomli==2.0.1 # mypy # pylint # pytest -tomlkit==0.11.8 +tomlkit==0.12.1 # via pylint tornado==6.3.2 # via diff --git a/hail/python/hailtop/fs/stat_result.py b/hail/python/hailtop/fs/stat_result.py index b28a8ae1252..a2bd49087e0 100644 --- a/hail/python/hailtop/fs/stat_result.py +++ b/hail/python/hailtop/fs/stat_result.py @@ -1,7 +1,7 @@ from enum import Enum, auto from typing import Dict, NamedTuple, Optional, Union, Any -import hurry.filesize +from hailtop.utils.filesize import filesize class FileType(Enum): @@ -27,6 +27,6 @@ def to_legacy_dict(self) -> Dict[str, Any]: 'owner': self.owner, 'is_dir': self.is_dir(), 'size_bytes': self.size, - 'size': hurry.filesize.size(self.size), + 'size': filesize(self.size), 'modification_time': self.modification_time, } diff --git a/hail/python/hailtop/utils/filesize.py b/hail/python/hailtop/utils/filesize.py new file mode 100644 index 00000000000..effc1d90e0c --- /dev/null +++ b/hail/python/hailtop/utils/filesize.py @@ -0,0 +1,17 @@ +_PREFIXES = ["B", "K", "M", "G", "T", "P", "E", "Z", "Y"] + + +def filesize(size: int) -> str: + """ + Renders the given number as a human-readable filesize using binary multiple-byte units (e.g. "MiB", not "MB"). + Rounds down to the nearest integer value and multiple-byte unit (e.g. ``filesize((1024**3) - 1)`` returns + ``"1023MiB"``, not ``"1GiB"`` or ``"1023.9999990463257MiB"``). + """ + if size < 0: + raise ValueError(f"Expected filesize to be non-negative, but received a value of {size} bytes.") + idx = 0 + while size >= 1024 and idx < len(_PREFIXES) - 1: + size //= 1024 + idx += 1 + suffix = "" if idx == 0 else "iB" + return f"{size}{_PREFIXES[idx]}{suffix}" diff --git a/hail/python/pinned-requirements.txt b/hail/python/pinned-requirements.txt index cce6e011240..5062183ad4b 100644 --- a/hail/python/pinned-requirements.txt +++ b/hail/python/pinned-requirements.txt @@ -155,8 +155,6 @@ humanize==1.1.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -hurry-filesize==0.9 - # via -r hail/hail/python/requirements.txt idna==3.4 # via # -c hail/hail/python/hailtop/pinned-requirements.txt @@ -374,6 +372,3 @@ yarl==1.9.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # aiohttp - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/hail/python/requirements.txt b/hail/python/requirements.txt index 56065fc4855..0674fefa847 100644 --- a/hail/python/requirements.txt +++ b/hail/python/requirements.txt @@ -8,7 +8,6 @@ decorator<5 Deprecated>=1.2.10,<1.3 dill>=0.3.1.1,<0.4 frozenlist>=1.3.1,<2 -hurry.filesize>=0.9,<1 numpy<2 pandas>=2,<3 parsimonious<1 diff --git a/hail/python/test/hailtop/utils/test_filesize.py b/hail/python/test/hailtop/utils/test_filesize.py new file mode 100644 index 00000000000..7eb3aeda10a --- /dev/null +++ b/hail/python/test/hailtop/utils/test_filesize.py @@ -0,0 +1,25 @@ +from pytest import raises +from hailtop.utils.filesize import filesize + +def test_filesize(): + for n in [-1, -1023, -1024, -1025, -1024**3]: + with raises(ValueError): + filesize(n) + assert filesize(0) == "0B" + assert filesize(1) == "1B" + assert filesize(2) == "2B" + assert filesize(1023) == "1023B" + assert filesize(1024) == "1KiB" + assert filesize(1025) == "1KiB" + prefixes = ["K", "M", "G", "T", "P", "E", "Z", "Y"] + for exp in range(2, 9): + assert filesize(1024 ** exp - 1) == f"1023{prefixes[exp - 2]}iB" + assert filesize(1024 ** exp) == f"1{prefixes[exp - 1]}iB" + assert filesize(1024 ** exp + 1) == f"1{prefixes[exp - 1]}iB" + assert filesize(1024 ** exp * 2) == f"2{prefixes[exp - 1]}iB" + assert filesize(1024 ** 9 - 1) == "1023YiB" + assert filesize(1024 ** 9) == "1024YiB" + assert filesize(1024 ** 9 + 1) == "1024YiB" + assert filesize(1024 ** 9 * 2) == "2048YiB" + assert filesize(1024 ** 10) == "1048576YiB" + From 4446b91ac4600b3df942a2f1f51c514fcaabfce3 Mon Sep 17 00:00:00 2001 From: jigold Date: Wed, 2 Aug 2023 10:40:01 -0400 Subject: [PATCH 054/180] [batch] Fix rare bug in list batches v2 test (#13350) --- batch/test/test_batch.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 336ab2d6a9a..0ebf78ca2ae 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -314,14 +314,17 @@ def assert_batch_ids(expected: Set[int], q=None): def test_list_batches_v2(client: BatchClient): - # replace any occurrences of the substring "b2" in the tag to avoid collisions with the batch name for the partial - # match test - tag = secrets.token_urlsafe(64).replace("b2", "00") - bb1 = create_batch(client, attributes={'tag': tag, 'name': 'b1'}) + tag = secrets.token_urlsafe(64) + partial_match_prefix = secrets.token_urlsafe(10) + bb1 = create_batch( + client, attributes={'tag': tag, 'name': 'b1', 'partial_match_name': f'{partial_match_prefix}-b1'} + ) bb1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) b1 = bb1.submit() - bb2 = create_batch(client, attributes={'tag': tag, 'name': 'b2'}) + bb2 = create_batch( + client, attributes={'tag': tag, 'name': 'b2', 'partial_match_name': f'{partial_match_prefix}-b2'} + ) bb2.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) b2 = bb2.submit() @@ -367,7 +370,7 @@ def assert_batch_ids(expected: Set[int], q=None): assert_batch_ids( {b2.id}, f''' -b2 +{partial_match_prefix[3:]}-b2 tag={tag} ''', ) From b30dd051d00dac53c2924bd82e76ad6a49b88577 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 2 Aug 2023 14:01:17 -0400 Subject: [PATCH 055/180] [lint] Add aiohttp handler types and remove some pylint disable directives (#13307) Post-vacation brain is mushy so I squashed some poor typing that my nvim lsp has been mad at me about for ages. Specifically, added sufficient type signatures to our aiohttp handler decorators, removed some unnecessary pylint ignore directives, and added a bit of typing to the `userdata` dict. There should be no changes in functionality. --- auth/auth/auth.py | 68 ++++++++-------- batch/batch/driver/main.py | 38 ++++----- batch/batch/front_end/front_end.py | 122 ++++++++++++++-------------- ci/ci/ci.py | 41 ++++++---- gear/gear/__init__.py | 3 +- gear/gear/auth.py | 44 ++++++---- gear/gear/auth_utils.py | 5 +- web_common/web_common/web_common.py | 11 ++- 8 files changed, 181 insertions(+), 151 deletions(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index 9fbbeb46916..fb9774c9879 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -5,7 +5,6 @@ import re from typing import List, Optional -import aiohttp import aiohttp_session import kubernetes_asyncio.client import kubernetes_asyncio.client.rest @@ -19,6 +18,7 @@ Database, K8sCache, Transaction, + UserData, check_csrf_token, create_session, json_request, @@ -180,20 +180,20 @@ def _delete(key): @routes.get('/healthcheck') -async def get_healthcheck(request): # pylint: disable=W0613 +async def get_healthcheck(_) -> web.Response: return web.Response() @routes.get('') @routes.get('/') @auth.web_maybe_authenticated_user -async def get_index(request, userdata): # pylint: disable=unused-argument +async def get_index(request: web.Request, userdata: Optional[UserData]) -> web.Response: return await render_template('auth', request, userdata, 'index.html', {}) @routes.get('/creating') @auth.web_maybe_authenticated_user -async def creating_account(request, userdata): +async def creating_account(request: web.Request, userdata: Optional[UserData]) -> web.Response: db = request.app['db'] session = await aiohttp_session.get_session(request) if 'pending' in session: @@ -207,7 +207,7 @@ async def creating_account(request, userdata): if user is None: set_message(session, f'Account does not exist for login id {login_id}.', 'error') - return aiohttp.web.HTTPFound(deploy_config.external_url('auth', '')) + return web.HTTPFound(deploy_config.external_url('auth', '')) page_context = {'username': user['username'], 'state': user['state'], 'login_id': user['login_id']} @@ -218,7 +218,7 @@ async def creating_account(request, userdata): session_id = await create_session(db, user['id']) session['session_id'] = session_id set_message(session, f'Account has been created for {user["username"]}.', 'info') - return aiohttp.web.HTTPFound(next_page) + return web.HTTPFound(next_page) assert user['state'] == 'creating' session['pending'] = True @@ -226,7 +226,7 @@ async def creating_account(request, userdata): session['next'] = next_page return await render_template('auth', request, userdata, 'account-creating.html', page_context) - return aiohttp.web.HTTPUnauthorized() + raise web.HTTPUnauthorized() @routes.get('/creating/wait') @@ -287,7 +287,7 @@ async def signup(request): session['caller'] = 'signup' session['flow'] = flow_data - return aiohttp.web.HTTPFound(flow_data['authorization_url']) + return web.HTTPFound(flow_data['authorization_url']) @routes.get('/login') @@ -302,7 +302,7 @@ async def login(request): session['caller'] = 'login' session['flow'] = flow_data - return aiohttp.web.HTTPFound(flow_data['authorization_url']) + return web.HTTPFound(flow_data['authorization_url']) @routes.get('/oauth2callback') @@ -336,7 +336,7 @@ async def callback(request): if user is None: if caller == 'login': set_message(session, f'Account does not exist for login id {login_id}', 'error') - return aiohttp.web.HTTPFound(deploy_config.external_url('auth', '')) + return web.HTTPFound(deploy_config.external_url('auth', '')) assert caller == 'signup' @@ -375,12 +375,12 @@ async def callback(request): set_message(session, f'Account has already been created for {user["username"]}.', 'info') session_id = await create_session(db, user['id']) session['session_id'] = session_id - return aiohttp.web.HTTPFound(next_page) + return web.HTTPFound(next_page) @routes.post('/api/v1alpha/users/{user}/create') @auth.rest_authenticated_developers_only -async def create_user(request: web.Request, userdata): # pylint: disable=unused-argument +async def create_user(request: web.Request, _) -> web.Response: db: Database = request.app['db'] username = request.match_info['user'] @@ -420,7 +420,7 @@ async def create_user(request: web.Request, userdata): # pylint: disable=unused @routes.get('/user') @auth.web_authenticated_users_only() -async def user_page(request, userdata): +async def user_page(request: web.Request, userdata: UserData) -> web.Response: return await render_template('auth', request, userdata, 'user.html', {'cloud': CLOUD}) @@ -436,7 +436,7 @@ async def create_copy_paste_token(db, session_id, max_age_secs=300): @routes.post('/copy-paste-token') @check_csrf_token @auth.web_authenticated_users_only() -async def get_copy_paste_token(request, userdata): +async def get_copy_paste_token(request: web.Request, userdata: UserData) -> web.Response: session = await aiohttp_session.get_session(request) session_id = session['session_id'] db = request.app['db'] @@ -447,7 +447,7 @@ async def get_copy_paste_token(request, userdata): @routes.post('/api/v1alpha/copy-paste-token') @auth.rest_authenticated_users_only -async def get_copy_paste_token_api(request, userdata): +async def get_copy_paste_token_api(request: web.Request, userdata: UserData) -> web.Response: session_id = userdata['session_id'] db = request.app['db'] copy_paste_token = await create_copy_paste_token(db, session_id) @@ -457,7 +457,7 @@ async def get_copy_paste_token_api(request, userdata): @routes.post('/logout') @check_csrf_token @auth.web_maybe_authenticated_user -async def logout(request, userdata): +async def logout(request: web.Request, userdata: Optional[UserData]) -> web.HTTPFound: if not userdata: return web.HTTPFound(deploy_config.external_url('auth', '')) @@ -472,7 +472,7 @@ async def logout(request, userdata): @routes.get('/api/v1alpha/login') -async def rest_login(request): +async def rest_login(request: web.Request) -> web.Response: callback_port = request.query['callback_port'] callback_uri = f'http://127.0.0.1:{callback_port}/oauth2callback' flow_data = request.app['flow_client'].initiate_flow(callback_uri) @@ -486,7 +486,7 @@ async def rest_login(request): @routes.get('/roles') @auth.web_authenticated_developers_only() -async def get_roles(request, userdata): +async def get_roles(request: web.Request, userdata: UserData) -> web.Response: db = request.app['db'] roles = [x async for x in db.select_and_fetchall('SELECT * FROM roles;')] page_context = {'roles': roles} @@ -496,11 +496,11 @@ async def get_roles(request, userdata): @routes.post('/roles') @check_csrf_token @auth.web_authenticated_developers_only() -async def post_create_role(request, userdata): # pylint: disable=unused-argument +async def post_create_role(request: web.Request, _) -> web.HTTPFound: session = await aiohttp_session.get_session(request) db = request.app['db'] post = await request.post() - name = post['name'] + name = str(post['name']) role_id = await db.execute_insertone( ''' @@ -517,7 +517,7 @@ async def post_create_role(request, userdata): # pylint: disable=unused-argumen @routes.get('/users') @auth.web_authenticated_developers_only() -async def get_users(request, userdata): +async def get_users(request: web.Request, userdata: UserData) -> web.Response: db = request.app['db'] users = [x async for x in db.select_and_fetchall('SELECT * FROM users;')] page_context = {'users': users} @@ -527,18 +527,16 @@ async def get_users(request, userdata): @routes.post('/users') @check_csrf_token @auth.web_authenticated_developers_only() -async def post_create_user(request, userdata): # pylint: disable=unused-argument +async def post_create_user(request: web.Request, _) -> web.HTTPFound: session = await aiohttp_session.get_session(request) db = request.app['db'] post = await request.post() - username = post['username'] - login_id = post.get('login_id', '') + username = str(post['username']) + login_id = str(post['login_id']) if 'login_id' in post else None is_developer = post.get('is_developer') == '1' is_service_account = post.get('is_service_account') == '1' try: - if login_id == '': - login_id = None created_user = await insert_new_user(db, username, login_id, is_developer, is_service_account) except AuthUserError as e: set_message(session, e.message, 'error') @@ -554,7 +552,7 @@ async def post_create_user(request, userdata): # pylint: disable=unused-argumen @routes.get('/api/v1alpha/users') @auth.rest_authenticated_developers_only -async def rest_get_users(request, userdata): # pylint: disable=unused-argument +async def rest_get_users(request: web.Request, _) -> web.Response: db: Database = request.app['db'] _query = ''' SELECT id, username, login_id, state, is_developer, is_service_account, hail_identity @@ -566,7 +564,7 @@ async def rest_get_users(request, userdata): # pylint: disable=unused-argument @routes.get('/api/v1alpha/users/{user}') @auth.rest_authenticated_developers_only -async def rest_get_user(request, userdata): # pylint: disable=unused-argument +async def rest_get_user(request: web.Request, _) -> web.Response: db: Database = request.app['db'] username = request.match_info['user'] @@ -606,12 +604,12 @@ async def _delete_user(db: Database, username: str, id: Optional[str]): @routes.post('/users/delete') @check_csrf_token @auth.web_authenticated_developers_only() -async def delete_user(request, userdata): # pylint: disable=unused-argument +async def delete_user(request: web.Request, _) -> web.HTTPFound: session = await aiohttp_session.get_session(request) db = request.app['db'] post = await request.post() - id = post['id'] - username = post['username'] + id = str(post['id']) + username = str(post['username']) try: await _delete_user(db, username, id) @@ -624,14 +622,14 @@ async def delete_user(request, userdata): # pylint: disable=unused-argument @routes.delete('/api/v1alpha/users/{user}') @auth.rest_authenticated_developers_only -async def rest_delete_user(request: web.Request, userdata): # pylint: disable=unused-argument +async def rest_delete_user(request: web.Request, _) -> web.Response: db = request.app['db'] username = request.match_info['user'] try: await _delete_user(db, username, None) except UnknownUser as e: - return e.http_response() + raise e.http_response() return web.json_response() @@ -702,7 +700,7 @@ async def maybe_pop_token(tx): @routes.post('/api/v1alpha/logout') @auth.rest_authenticated_users_only -async def rest_logout(request, userdata): +async def rest_logout(request: web.Request, userdata: UserData) -> web.Response: session_id = userdata['session_id'] db = request.app['db'] await db.just_execute('DELETE FROM sessions WHERE session_id = %s;', session_id) @@ -710,7 +708,7 @@ async def rest_logout(request, userdata): return web.Response(status=200) -async def get_userinfo(request, session_id): +async def get_userinfo(request: web.Request, session_id: str) -> UserData: # b64 encoding of 32-byte session ID is 44 bytes if len(session_id) != 44: log.info('Session id != 44 bytes') diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 7573f91ffcf..8588d47d7bc 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -7,7 +7,7 @@ import signal from collections import defaultdict, namedtuple from functools import wraps -from typing import Any, Dict, Set, Tuple +from typing import Any, Awaitable, Callable, Dict, Set, Tuple import aiohttp_session import dictdiffer @@ -33,6 +33,7 @@ setup_aiohttp_session, transaction, ) +from gear.auth import AIOHTTPHandler from gear.clients import get_cloud_async_fs from gear.profiling import install_profiler_if_requested from hailtop import aiotools, httpx @@ -71,6 +72,7 @@ ) from .canceller import Canceller from .driver import CloudDriver +from .instance import Instance from .instance_collection import InstanceCollectionManager, JobPrivateInstanceManager, Pool from .job import mark_job_complete, mark_job_started @@ -107,7 +109,7 @@ def instance_token(request): return request.headers.get('X-Hail-Instance-Token') or authorization_token(request) -def activating_instances_only(fun): +def activating_instances_only(fun: Callable[[web.Request, Instance], Awaitable[web.StreamResponse]]) -> AIOHTTPHandler: @wraps(fun) async def wrapped(request): instance = instance_from_request(request) @@ -133,14 +135,12 @@ async def wrapped(request): log.info(f'instance {instance.name}, activation token not found in database') raise web.HTTPUnauthorized() - resp = await fun(request, instance) - - return resp + return await fun(request, instance) return wrapped -def active_instances_only(fun): +def active_instances_only(fun: Callable[[web.Request, Instance], Awaitable[web.StreamResponse]]) -> AIOHTTPHandler: @wraps(fun) async def wrapped(request): instance = instance_from_request(request) @@ -172,13 +172,13 @@ async def wrapped(request): @routes.get('/healthcheck') -async def get_healthcheck(request): # pylint: disable=W0613 +async def get_healthcheck(_) -> web.Response: return web.Response() @routes.get('/check_invariants') @auth.rest_authenticated_developers_only -async def get_check_invariants(request, userdata): # pylint: disable=unused-argument +async def get_check_invariants(request: web.Request, _) -> web.Response: db: Database = request.app['db'] incremental_result, resource_agg_result = await asyncio.gather( check_incremental(db), check_resource_aggregation(db), return_exceptions=True @@ -265,14 +265,14 @@ async def activate_instance_1(request, instance): # deprecated @routes.get('/api/v1alpha/instances/gsa_key') @activating_instances_only -async def get_gsa_key(request, instance): # pylint: disable=unused-argument +async def get_gsa_key(_, instance: Instance) -> web.Response: return await asyncio.shield(get_gsa_key_1(instance)) # deprecated @routes.get('/api/v1alpha/instances/credentials') @activating_instances_only -async def get_credentials(request, instance): # pylint: disable=unused-argument +async def get_credentials(_, instance: Instance) -> web.Response: return await asyncio.shield(get_credentials_1(instance)) @@ -292,7 +292,7 @@ async def deactivate_instance_1(instance): @routes.post('/api/v1alpha/instances/deactivate') @active_instances_only @add_metadata_to_request -async def deactivate_instance(request, instance): # pylint: disable=unused-argument +async def deactivate_instance(_, instance: Instance) -> web.Response: await asyncio.shield(deactivate_instance_1(instance)) return web.Response() @@ -300,14 +300,14 @@ async def deactivate_instance(request, instance): # pylint: disable=unused-argu @routes.post('/instances/{instance_name}/kill') @check_csrf_token @auth.web_authenticated_developers_only() -async def kill_instance(request, userdata): # pylint: disable=unused-argument +async def kill_instance(request: web.Request, _) -> web.HTTPFound: instance_name = request.match_info['instance_name'] inst_coll_manager: InstanceCollectionManager = request.app['driver'].inst_coll_manager instance = inst_coll_manager.get_instance(instance_name) if instance is None: - return web.HTTPNotFound() + raise web.HTTPNotFound() session = await aiohttp_session.get_session(request) if instance.state == 'active': @@ -563,7 +563,7 @@ def validate_int(session, name, value, predicate, description): @routes.post('/configure-feature-flags') @check_csrf_token @auth.web_authenticated_developers_only() -async def configure_feature_flags(request, userdata): # pylint: disable=unused-argument +async def configure_feature_flags(request: web.Request, _) -> web.HTTPFound: app = request.app db: Database = app['db'] post = await request.post() @@ -587,7 +587,7 @@ async def configure_feature_flags(request, userdata): # pylint: disable=unused- @routes.post('/config-update/pool/{pool}') @check_csrf_token @auth.web_authenticated_developers_only() -async def pool_config_update(request, userdata): # pylint: disable=unused-argument +async def pool_config_update(request: web.Request, _) -> web.HTTPFound: app = request.app db: Database = app['db'] inst_coll_manager: InstanceCollectionManager = app['driver'].inst_coll_manager @@ -760,7 +760,7 @@ async def pool_config_update(request, userdata): # pylint: disable=unused-argum job_queue_scheduling_window_secs=job_queue_scheduling_window_secs, ) - current_client_pool_config = json.loads(post['_pool_config_json']) + current_client_pool_config = json.loads(str(post['_pool_config_json'])) current_server_pool_config = pool.config() client_items = current_client_pool_config.items() @@ -793,7 +793,7 @@ async def pool_config_update(request, userdata): # pylint: disable=unused-argum @routes.post('/config-update/jpim') @check_csrf_token @auth.web_authenticated_developers_only() -async def job_private_config_update(request, userdata): # pylint: disable=unused-argument +async def job_private_config_update(request: web.Request, _) -> web.HTTPFound: app = request.app jpim: JobPrivateInstanceManager = app['driver'].job_private_inst_manager @@ -938,7 +938,7 @@ async def get_job_private_inst_manager(request, userdata): @routes.post('/freeze') @check_csrf_token @auth.web_authenticated_developers_only() -async def freeze_batch(request, userdata): # pylint: disable=unused-argument +async def freeze_batch(request: web.Request, _) -> web.HTTPFound: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) @@ -963,7 +963,7 @@ async def freeze_batch(request, userdata): # pylint: disable=unused-argument @routes.post('/unfreeze') @check_csrf_token @auth.web_authenticated_developers_only() -async def unfreeze_batch(request, userdata): # pylint: disable=unused-argument +async def unfreeze_batch(request: web.Request, _) -> web.HTTPFound: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index 4deddf2fa79..e58caf65c86 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -11,9 +11,10 @@ import traceback from functools import wraps from numbers import Number -from typing import Awaitable, Callable, Dict, Optional, Tuple, TypeVar, Union +from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, TypeVar, Union import aiohttp +import aiohttp.web_exceptions import aiohttp_session import humanize import pandas as pd @@ -31,6 +32,7 @@ AuthClient, Database, Transaction, + UserData, check_csrf_token, json_request, json_response, @@ -118,12 +120,12 @@ P = ParamSpec('P') -def rest_authenticated_developers_or_auth_only(fun): +def rest_authenticated_developers_or_auth_only(fun: Callable[[web.Request], Awaitable[web.StreamResponse]]): @auth.rest_authenticated_users_only @wraps(fun) - async def wrapped(request, userdata, *args, **kwargs): + async def wrapped(request: web.Request, userdata: UserData) -> web.StreamResponse: if userdata['is_developer'] == 1 or userdata['username'] == 'auth': - return await fun(request, userdata, *args, **kwargs) + return await fun(request) raise web.HTTPUnauthorized() return wrapped @@ -161,33 +163,33 @@ async def _user_can_access(db: Database, batch_id: int, user: str): return record is not None -def rest_billing_project_users_only(fun): +def rest_billing_project_users_only(fun: Callable[[web.Request, UserData, int], Awaitable[web.StreamResponse]]): @auth.rest_authenticated_users_only @wraps(fun) - async def wrapped(request, userdata, *args, **kwargs): + async def wrapped(request: web.Request, userdata: UserData) -> web.StreamResponse: db = request.app['db'] batch_id = int(request.match_info['batch_id']) user = userdata['username'] permitted_user = await _user_can_access(db, batch_id, user) if not permitted_user: raise web.HTTPNotFound() - return await fun(request, userdata, batch_id, *args, **kwargs) + return await fun(request, userdata, batch_id) return wrapped def web_billing_project_users_only(redirect=True): - def wrap(fun): + def wrap(fun: Callable[[web.Request, UserData, int], Awaitable[web.StreamResponse]]): @auth.web_authenticated_users_only(redirect) @wraps(fun) - async def wrapped(request, userdata, *args, **kwargs): + async def wrapped(request: web.Request, userdata: UserData) -> web.StreamResponse: db = request.app['db'] batch_id = int(request.match_info['batch_id']) user = userdata['username'] permitted_user = await _user_can_access(db, batch_id, user) if not permitted_user: raise web.HTTPNotFound() - return await fun(request, userdata, batch_id, *args, **kwargs) + return await fun(request, userdata, batch_id) return wrapped @@ -201,23 +203,23 @@ def cast_query_param_to_int(param: Optional[str]) -> Optional[int]: @routes.get('/healthcheck') -async def get_healthcheck(request): # pylint: disable=W0613 +async def get_healthcheck(_) -> web.Response: return web.Response() @routes.get('/api/v1alpha/version') -async def rest_get_version(request): # pylint: disable=W0613 +async def rest_get_version(_) -> web.Response: return web.Response(text=version()) @routes.get('/api/v1alpha/cloud') -async def rest_cloud(request): # pylint: disable=W0613 +async def rest_cloud(_) -> web.Response: return web.Response(text=CLOUD) @routes.get('/api/v1alpha/supported_regions') @auth.rest_authenticated_users_only -async def rest_get_supported_regions(request, userdata): # pylint: disable=unused-argument +async def rest_get_supported_regions(request: web.Request, _) -> web.Response: return json_response(list(request.app['regions'].keys())) @@ -292,7 +294,7 @@ async def _get_jobs(request, batch_id: int, version: int, q: str, last_job_id: O @routes.get('/api/v1alpha/batches/{batch_id}/jobs') @rest_billing_project_users_only @add_metadata_to_request -async def get_jobs_v1(request: web.Request, userdata: dict, batch_id: int): # pylint: disable=unused-argument +async def get_jobs_v1(request: web.Request, _, batch_id: int) -> web.Response: q = request.query.get('q', '') last_job_id = cast_query_param_to_int(request.query.get('last_job_id')) resp = await _handle_api_error(_get_jobs, request, batch_id, 1, q, last_job_id) @@ -303,7 +305,7 @@ async def get_jobs_v1(request: web.Request, userdata: dict, batch_id: int): # p @routes.get('/api/v2alpha/batches/{batch_id}/jobs') @rest_billing_project_users_only @add_metadata_to_request -async def get_jobs_v2(request: web.Request, userdata: dict, batch_id: int): # pylint: disable=unused-argument +async def get_jobs_v2(request: web.Request, _, batch_id: int) -> web.Response: q = request.query.get('q', '') last_job_id = cast_query_param_to_int(request.query.get('last_job_id')) resp = await _handle_api_error(_get_jobs, request, batch_id, 2, q, last_job_id) @@ -587,7 +589,7 @@ async def _get_full_job_status(app, record): @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log') @rest_billing_project_users_only @add_metadata_to_request -async def get_job_log(request, userdata, batch_id): # pylint: disable=unused-argument +async def get_job_log(request: web.Request, _, batch_id: int) -> web.Response: job_id = int(request.match_info['job_id']) job_log_bytes = await _get_job_log(request.app, batch_id, job_id) job_log_strings: Dict[str, Optional[str]] = {} @@ -616,7 +618,7 @@ async def get_job_container_log(request, batch_id): @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log/{container}') @rest_billing_project_users_only @add_metadata_to_request -async def rest_get_job_container_log(request, userdata, batch_id): # pylint: disable=unused-argument +async def rest_get_job_container_log(request, _, batch_id) -> web.Response: return await get_job_container_log(request, batch_id) @@ -687,7 +689,7 @@ def check_service_account_permissions(user, sa): @routes.post('/api/v1alpha/batches/{batch_id}/jobs/create') @auth.rest_authenticated_users_only @add_metadata_to_request -async def create_jobs(request: aiohttp.web.Request, userdata: dict): +async def create_jobs(request: web.Request, userdata: UserData) -> web.Response: app = request.app batch_id = int(request.match_info['batch_id']) job_specs = await json_request(request) @@ -697,7 +699,7 @@ async def create_jobs(request: aiohttp.web.Request, userdata: dict): @routes.post('/api/v1alpha/batches/{batch_id}/updates/{update_id}/jobs/create') @auth.rest_authenticated_users_only @add_metadata_to_request -async def create_jobs_for_update(request: aiohttp.web.Request, userdata: dict): +async def create_jobs_for_update(request: web.Request, userdata: UserData) -> web.Response: app = request.app if app['frozen']: @@ -718,7 +720,9 @@ def assert_is_sha_1_hex_string(revision: str): raise web.HTTPBadRequest(reason=f'revision must be 40 character hexadecimal encoded SHA-1, got: {revision}') -async def _create_jobs(userdata: dict, job_specs: dict, batch_id: int, update_id: int, app: aiohttp.web.Application): +async def _create_jobs( + userdata, job_specs: List[Dict[str, Any]], batch_id: int, update_id: int, app: web.Application +) -> web.Response: db: Database = app['db'] file_store: FileStore = app['file_store'] user = userdata['username'] @@ -1155,7 +1159,7 @@ async def insert_jobs_into_db(tx): ) except asyncio.CancelledError: raise - except aiohttp.web.HTTPException: + except web.HTTPException: raise except Exception as err: raise ValueError( @@ -1219,7 +1223,7 @@ async def create_batch(request, userdata): return json_response({'id': id, 'update_id': update_id}) -async def _create_batch(batch_spec: dict, userdata: dict, db: Database): +async def _create_batch(batch_spec: dict, userdata, db: Database) -> int: try: validate_batch(batch_spec) except ValidationError as e: @@ -1526,14 +1530,14 @@ async def _delete_batch(app, batch_id): @routes.get('/api/v1alpha/batches/{batch_id}') @rest_billing_project_users_only @add_metadata_to_request -async def get_batch(request, userdata, batch_id): # pylint: disable=unused-argument +async def get_batch(request: web.Request, _, batch_id: int) -> web.Response: return json_response(await _get_batch(request.app, batch_id)) @routes.patch('/api/v1alpha/batches/{batch_id}/cancel') @rest_billing_project_users_only @add_metadata_to_request -async def cancel_batch(request, userdata, batch_id): # pylint: disable=unused-argument +async def cancel_batch(request: web.Request, _, batch_id: int) -> web.Response: await _handle_api_error(_cancel_batch, request.app, batch_id) return web.Response() @@ -1633,7 +1637,7 @@ async def _commit_update(app: web.Application, batch_id: int, update_id: int, us @routes.delete('/api/v1alpha/batches/{batch_id}') @rest_billing_project_users_only @add_metadata_to_request -async def delete_batch(request, userdata, batch_id): # pylint: disable=unused-argument +async def delete_batch(request: web.Request, _, batch_id: int) -> web.Response: await _delete_batch(request.app, batch_id) return web.Response() @@ -1675,12 +1679,12 @@ async def ui_batch(request, userdata, batch_id): @check_csrf_token @web_billing_project_users_only(redirect=False) @catch_ui_error_in_dev -async def ui_cancel_batch(request, userdata, batch_id): # pylint: disable=unused-argument +async def ui_cancel_batch(request: web.Request, _, batch_id: int) -> web.HTTPFound: post = await request.post() q = post.get('q') - params = {} + params: Dict[str, str] = {} if q is not None: - params['q'] = q + params['q'] = str(q) session = await aiohttp_session.get_session(request) try: await _handle_ui_error(session, _cancel_batch, request.app, batch_id) @@ -1694,12 +1698,12 @@ async def ui_cancel_batch(request, userdata, batch_id): # pylint: disable=unuse @check_csrf_token @web_billing_project_users_only(redirect=False) @catch_ui_error_in_dev -async def ui_delete_batch(request, userdata, batch_id): # pylint: disable=unused-argument +async def ui_delete_batch(request: web.Request, _, batch_id: int) -> web.HTTPFound: post = await request.post() q = post.get('q') - params = {} + params: Dict[str, str] = {} if q is not None: - params['q'] = q + params['q'] = str(q) await _delete_batch(request.app, batch_id) session = await aiohttp_session.get_session(request) set_message(session, f'Batch {batch_id} deleted.', 'info') @@ -1710,7 +1714,7 @@ async def ui_delete_batch(request, userdata, batch_id): # pylint: disable=unuse @routes.get('/batches', name='batches') @auth.web_authenticated_users_only() @catch_ui_error_in_dev -async def ui_batches(request: web.Request, userdata: dict): +async def ui_batches(request: web.Request, userdata: UserData) -> web.Response: session = await aiohttp_session.get_session(request) user = userdata['username'] q = request.query.get('q', f'user:{user}') @@ -1837,7 +1841,7 @@ async def _get_attempts(app, batch_id, job_id): @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}/attempts') @rest_billing_project_users_only -async def get_attempts(request, userdata, batch_id): # pylint: disable=unused-argument +async def get_attempts(request: web.Request, _, batch_id: int) -> web.Response: job_id = int(request.match_info['job_id']) attempts = await _get_attempts(request.app, batch_id, job_id) return json_response(attempts) @@ -1846,7 +1850,7 @@ async def get_attempts(request, userdata, batch_id): # pylint: disable=unused-a @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}') @rest_billing_project_users_only @add_metadata_to_request -async def get_job(request, userdata, batch_id): # pylint: disable=unused-argument +async def get_job(request: web.Request, _, batch_id: int) -> web.Response: job_id = int(request.match_info['job_id']) status = await _get_job(request.app, batch_id, job_id) return json_response(status) @@ -2015,11 +2019,11 @@ def add_trace(time, measurement, row, col, container_name, show_legend): limit_props = {'color': 'black', 'width': 2} if memory_limit_bytes is not None: - fig.add_hline(memory_limit_bytes, row=1, col=2, line=limit_props) + fig.add_hline(memory_limit_bytes, row=1, col=2, line=limit_props) # type: ignore if non_io_storage_limit_bytes is not None: - fig.add_hline(non_io_storage_limit_bytes, row=3, col=1, line=limit_props) + fig.add_hline(non_io_storage_limit_bytes, row=3, col=1, line=limit_props) # type: ignore if io_storage_limit_bytes is not None: - fig.add_hline(io_storage_limit_bytes, row=3, col=2, line=limit_props) + fig.add_hline(io_storage_limit_bytes, row=3, col=2, line=limit_props) # type: ignore fig.update_layout( showlegend=True, @@ -2044,7 +2048,7 @@ def add_trace(time, measurement, row, col, container_name, show_legend): @routes.get('/batches/{batch_id}/jobs/{job_id}/jvm_profile') @web_billing_project_users_only() @catch_ui_error_in_dev -async def ui_get_jvm_profile(request, userdata, batch_id): # pylint: disable=unused-argument +async def ui_get_jvm_profile(request: web.Request, _, batch_id: int) -> web.Response: app = request.app job_id = int(request.match_info['job_id']) profile = await _get_jvm_profile(app, batch_id, job_id) @@ -2171,7 +2175,7 @@ async def ui_get_job(request, userdata, batch_id): @routes.get('/batches/{batch_id}/jobs/{job_id}/log/{container}') @web_billing_project_users_only() @catch_ui_error_in_dev -async def ui_get_job_log(request, userdata, batch_id): # pylint: disable=unused-argument +async def ui_get_job_log(request: web.Request, _, batch_id: int) -> web.Response: return await get_job_container_log(request, batch_id) @@ -2246,7 +2250,7 @@ async def insert(tx): @routes.post('/api/v1alpha/billing_limits/{billing_project}/edit') @rest_authenticated_developers_or_auth_only -async def post_edit_billing_limits(request, userdata): # pylint: disable=unused-argument +async def post_edit_billing_limits(request: web.Request) -> web.Response: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] data = await json_request(request) @@ -2259,7 +2263,7 @@ async def post_edit_billing_limits(request, userdata): # pylint: disable=unused @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_edit_billing_limits_ui(request, userdata): # pylint: disable=unused-argument +async def post_edit_billing_limits_ui(request: web.Request, _) -> web.HTTPFound: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] post = await request.post() @@ -2267,12 +2271,12 @@ async def post_edit_billing_limits_ui(request, userdata): # pylint: disable=unu session = await aiohttp_session.get_session(request) try: await _handle_ui_error(session, _edit_billing_limit, db, billing_project, limit) - set_message(session, f'Modified limit {limit} for billing project {billing_project}.', 'info') + set_message(session, f'Modified limit {limit} for billing project {billing_project}.', 'info') # type: ignore finally: return web.HTTPFound(deploy_config.external_url('batch', '/billing_limits')) # pylint: disable=lost-exception -async def _query_billing(request, user=None): +async def _query_billing(request: web.Request, user: Optional[str] = None) -> Tuple[list, str, Optional[str]]: db: Database = request.app['db'] date_format = '%m/%d/%Y' @@ -2282,7 +2286,7 @@ async def _query_billing(request, user=None): default_end = None - async def parse_error(msg): + async def parse_error(msg: str) -> Tuple[list, str, None]: session = await aiohttp_session.get_session(request) set_message(session, msg, 'error') return ([], default_start_str, default_end) @@ -2309,7 +2313,7 @@ async def parse_error(msg): "billing_projects.`status` != 'deleted'", "billing_date >= %s", ] - where_args = [start] + where_args: List[Any] = [start] if end is not None: where_conditions.append("billing_date <= %s") @@ -2485,7 +2489,7 @@ async def delete(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_billing_projects_remove_user(request, userdata): # pylint: disable=unused-argument +async def post_billing_projects_remove_user(request: web.Request, _) -> web.HTTPFound: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] user = request.match_info['user'] @@ -2500,7 +2504,7 @@ async def post_billing_projects_remove_user(request, userdata): # pylint: disab @routes.post('/api/v1alpha/billing_projects/{billing_project}/users/{user}/remove') @rest_authenticated_developers_or_auth_only -async def api_get_billing_projects_remove_user(request, userdata): # pylint: disable=unused-argument +async def api_get_billing_projects_remove_user(request: web.Request) -> web.Response: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] user = request.match_info['user'] @@ -2555,7 +2559,7 @@ async def insert(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_billing_projects_add_user(request, userdata): # pylint: disable=unused-argument +async def post_billing_projects_add_user(request: web.Request, _) -> web.HTTPFound: db: Database = request.app['db'] post = await request.post() user = post['user'] @@ -2565,14 +2569,14 @@ async def post_billing_projects_add_user(request, userdata): # pylint: disable= try: await _handle_ui_error(session, _add_user_to_billing_project, db, billing_project, user) - set_message(session, f'Added user {user} to billing project {billing_project}.', 'info') + set_message(session, f'Added user {user} to billing project {billing_project}.', 'info') # type: ignore finally: return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/users/{user}/add') @rest_authenticated_developers_or_auth_only -async def api_billing_projects_add_user(request, userdata): # pylint: disable=unused-argument +async def api_billing_projects_add_user(request: web.Request) -> web.Response: db: Database = request.app['db'] user = request.match_info['user'] billing_project = request.match_info['billing_project'] @@ -2613,7 +2617,7 @@ async def insert(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_create_billing_projects(request, userdata): # pylint: disable=unused-argument +async def post_create_billing_projects(request: web.Request, _) -> web.HTTPFound: db: Database = request.app['db'] post = await request.post() billing_project = post['billing_project'] @@ -2621,14 +2625,14 @@ async def post_create_billing_projects(request, userdata): # pylint: disable=un session = await aiohttp_session.get_session(request) try: await _handle_ui_error(session, _create_billing_project, db, billing_project) - set_message(session, f'Added billing project {billing_project}.', 'info') + set_message(session, f'Added billing project {billing_project}.', 'info') # type: ignore finally: return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/create') @rest_authenticated_developers_or_auth_only -async def api_get_create_billing_projects(request, userdata): # pylint: disable=unused-argument +async def api_get_create_billing_projects(request: web.Request) -> web.Response: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] await _handle_api_error(_create_billing_project, db, billing_project) @@ -2674,7 +2678,7 @@ async def close_project(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_close_billing_projects(request, userdata): # pylint: disable=unused-argument +async def post_close_billing_projects(request: web.Request, _) -> web.HTTPFound: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] @@ -2688,7 +2692,7 @@ async def post_close_billing_projects(request, userdata): # pylint: disable=unu @routes.post('/api/v1alpha/billing_projects/{billing_project}/close') @rest_authenticated_developers_or_auth_only -async def api_close_billing_projects(request, userdata): # pylint: disable=unused-argument +async def api_close_billing_projects(request: web.Request) -> web.Response: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] @@ -2733,7 +2737,7 @@ async def post_reopen_billing_projects(request, userdata): # pylint: disable=un @routes.post('/api/v1alpha/billing_projects/{billing_project}/reopen') @rest_authenticated_developers_or_auth_only -async def api_reopen_billing_projects(request, userdata): # pylint: disable=unused-argument +async def api_reopen_billing_projects(request: web.Request) -> web.Response: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] await _handle_api_error(_reopen_billing_project, db, billing_project) @@ -2763,7 +2767,7 @@ async def delete_project(tx): @routes.post('/api/v1alpha/billing_projects/{billing_project}/delete') @rest_authenticated_developers_or_auth_only -async def api_delete_billing_projects(request, userdata): # pylint: disable=unused-argument +async def api_delete_billing_projects(request: web.Request) -> web.Response: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] @@ -2793,7 +2797,7 @@ async def _refresh(app): @routes.get('/') @auth.web_authenticated_users_only() @catch_ui_error_in_dev -async def index(request, userdata): # pylint: disable=unused-argument +async def index(request: web.Request, _) -> web.HTTPFound: location = request.app.router['batches'].url_for() raise web.HTTPFound(location=location) diff --git a/ci/ci/ci.py b/ci/ci/ci.py index ec344ec7efb..13fb6fdf2bf 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -4,10 +4,12 @@ import logging import os import traceback -from typing import Callable, Dict, List, Optional, Set +from typing import Callable, Dict, List, Optional, Set, Tuple import aiohttp_session # type: ignore import kubernetes_asyncio +import kubernetes_asyncio.client +import kubernetes_asyncio.config import uvloop # type: ignore import yaml from aiohttp import web @@ -20,6 +22,7 @@ from gear import ( AuthClient, Database, + UserData, check_csrf_token, json_request, json_response, @@ -132,13 +135,13 @@ async def watched_branch_config(app, wb: WatchedBranch, index: int) -> WatchedBr @routes.get('') @routes.get('/') @auth.web_authenticated_developers_only() -async def index(request, userdata): # pylint: disable=unused-argument +async def index(request: web.Request, userdata: UserData) -> web.Response: wb_configs = [await watched_branch_config(request.app, wb, i) for i, wb in enumerate(watched_branches)] page_context = {'watched_branches': wb_configs, 'frozen_merge_deploy': request.app['frozen_merge_deploy']} return await render_template('ci', request, userdata, 'index.html', page_context) -def wb_and_pr_from_request(request): +def wb_and_pr_from_request(request: web.Request) -> Tuple[WatchedBranch, PR]: watched_branch_index = int(request.match_info['watched_branch_index']) pr_number = int(request.match_info['pr_number']) @@ -160,7 +163,7 @@ def filter_jobs(jobs): @routes.get('/watched_branches/{watched_branch_index}/pr/{pr_number}') @auth.web_authenticated_developers_only() -async def get_pr(request, userdata): # pylint: disable=unused-argument +async def get_pr(request: web.Request, userdata: UserData) -> web.Response: wb, pr = wb_and_pr_from_request(request) page_context = {} @@ -223,7 +226,7 @@ async def retry_pr(wb, pr, request): @routes.post('/watched_branches/{watched_branch_index}/pr/{pr_number}/retry') @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) -async def post_retry_pr(request, userdata): # pylint: disable=unused-argument +async def post_retry_pr(request: web.Request, _) -> web.HTTPFound: wb, pr = wb_and_pr_from_request(request) await asyncio.shield(retry_pr(wb, pr, request)) @@ -309,7 +312,7 @@ def pr_requires_action(gh_username: str, pr_config: PRConfig) -> bool: @routes.get('/me') @auth.web_authenticated_developers_only() -async def get_user(request, userdata): +async def get_user(request: web.Request, userdata: UserData) -> web.Response: for authorized_user in AUTHORIZED_USERS: if authorized_user.hail_username == userdata['username']: user = authorized_user @@ -343,11 +346,11 @@ async def get_user(request, userdata): @routes.post('/authorize_source_sha') @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) -async def post_authorized_source_sha(request, userdata): # pylint: disable=unused-argument +async def post_authorized_source_sha(request: web.Request, _) -> web.HTTPFound: app = request.app db: Database = app['db'] post = await request.post() - sha = post['sha'].strip() + sha = str(post['sha']).strip() await db.execute_insertone('INSERT INTO authorized_shas (sha) VALUES (%s);', sha) log.info(f'authorized sha: {sha}') session = await aiohttp_session.get_session(request) @@ -356,7 +359,7 @@ async def post_authorized_source_sha(request, userdata): # pylint: disable=unus @routes.get('/healthcheck') -async def healthcheck(request): # pylint: disable=unused-argument +async def healthcheck(_) -> web.Response: return web.Response(status=200) @@ -439,7 +442,7 @@ async def batch_callback_handler(request): @routes.get('/api/v1alpha/deploy_status') @auth.rest_authenticated_developers_only -async def deploy_status(request, userdata): # pylint: disable=unused-argument +async def deploy_status(request: web.Request, _) -> web.Response: batch_client = request.app['batch_client'] async def get_failure_information(batch): @@ -473,7 +476,7 @@ async def fetch_job_and_log(j): @routes.post('/api/v1alpha/update') @auth.rest_authenticated_developers_only -async def post_update(request, userdata): # pylint: disable=unused-argument +async def post_update(request: web.Request, _) -> web.Response: log.info('developer triggered update') async def update_all(): @@ -486,7 +489,7 @@ async def update_all(): @routes.post('/api/v1alpha/dev_deploy_branch') @auth.rest_authenticated_developers_only -async def dev_deploy_branch(request, userdata): +async def dev_deploy_branch(request: web.Request, userdata: UserData) -> web.Response: app = request.app try: params = await json_request(request) @@ -545,7 +548,7 @@ async def batch_callback(request): @routes.post('/freeze_merge_deploy') @check_csrf_token @auth.web_authenticated_developers_only() -async def freeze_deploys(request, userdata): # pylint: disable=unused-argument +async def freeze_deploys(request: web.Request, _) -> web.HTTPFound: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) @@ -570,7 +573,7 @@ async def freeze_deploys(request, userdata): # pylint: disable=unused-argument @routes.post('/unfreeze_merge_deploy') @check_csrf_token @auth.web_authenticated_developers_only() -async def unfreeze_deploys(request, userdata): # pylint: disable=unused-argument +async def unfreeze_deploys(request: web.Request, _) -> web.HTTPFound: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) @@ -594,7 +597,7 @@ async def unfreeze_deploys(request, userdata): # pylint: disable=unused-argumen @routes.get('/namespaces') @auth.web_authenticated_developers_only() -async def get_active_namespaces(request, userdata): +async def get_active_namespaces(request: web.Request, userdata: UserData) -> web.Response: db: Database = request.app['db'] namespaces = [ r @@ -618,7 +621,7 @@ async def get_active_namespaces(request, userdata): @routes.post('/namespaces/{namespace}/services/add') @check_csrf_token @auth.web_authenticated_developers_only() -async def add_namespaced_service(request, userdata): # pylint: disable=unused-argument +async def add_namespaced_service(request: web.Request, _) -> web.HTTPFound: db: Database = request.app['db'] post = await request.post() service = post['service'] @@ -647,7 +650,7 @@ async def add_namespaced_service(request, userdata): # pylint: disable=unused-a @routes.post('/namespaces/add') @check_csrf_token @auth.web_authenticated_developers_only() -async def add_namespace(request, userdata): # pylint: disable=unused-argument +async def add_namespace(request: web.Request, _) -> web.HTTPFound: db: Database = request.app['db'] post = await request.post() namespace = post['namespace'] @@ -725,6 +728,7 @@ async def update_envoy_configs(db: Database, k8s_client): async def update_loop(app): + wb: Optional[WatchedBranch] = None while True: try: for wb in watched_branches: @@ -733,7 +737,8 @@ async def update_loop(app): except concurrent.futures.CancelledError: raise except Exception: # pylint: disable=broad-except - log.exception(f'{wb.branch.short_str()} update failed due to exception') + if wb: + log.exception(f'{wb.branch.short_str()} update failed due to exception') await asyncio.sleep(300) diff --git a/gear/gear/__init__.py b/gear/gear/__init__.py index a323f65fc7a..30d7565137e 100644 --- a/gear/gear/__init__.py +++ b/gear/gear/__init__.py @@ -1,4 +1,4 @@ -from .auth import AuthClient, maybe_parse_bearer_header +from .auth import AuthClient, UserData, maybe_parse_bearer_header from .auth_utils import create_session, insert_user from .csrf import check_csrf_token, new_csrf_token from .database import Database, Transaction, create_database_pool, resolve_test_db_endpoint, transaction @@ -19,6 +19,7 @@ 'transaction', 'maybe_parse_bearer_header', 'AuthClient', + 'UserData', 'monitor_endpoints_middleware', 'json_request', 'json_response', diff --git a/gear/gear/auth.py b/gear/gear/auth.py index 3d23706d56c..c9b67c49ec3 100644 --- a/gear/gear/auth.py +++ b/gear/gear/auth.py @@ -2,7 +2,7 @@ import logging import urllib.parse from functools import wraps -from typing import Optional, Tuple +from typing import Awaitable, Callable, Optional, Tuple, TypedDict import aiohttp import aiohttp_session @@ -23,50 +23,66 @@ TEN_SECONDS_IN_NANOSECONDS = int(1e10) +class UserData(TypedDict): + username: str + is_developer: bool + is_service_account: bool + hail_credentials_secret_name: str + tokens_secret_name: str + session_id: str + + def maybe_parse_bearer_header(value: str) -> Optional[str]: if value.startswith(BEARER): return value[len(BEARER) :] return None +AIOHTTPHandler = Callable[[web.Request], Awaitable[web.StreamResponse]] +AuthenticatedAIOHTTPHandler = Callable[[web.Request, UserData], Awaitable[web.StreamResponse]] +MaybeAuthenticatedAIOHTTPHandler = Callable[[web.Request, Optional[UserData]], Awaitable[web.StreamResponse]] + + class AuthClient: def __init__(self): self._userdata_cache = TimeLimitedMaxSizeCache( self._load_userdata, TEN_SECONDS_IN_NANOSECONDS, 100, 'session_userdata_cache' ) - def rest_authenticated_users_only(self, fun): - async def wrapped(request, *args, **kwargs): + def rest_authenticated_users_only(self, fun: AuthenticatedAIOHTTPHandler) -> AIOHTTPHandler: + async def wrapped(request: web.Request) -> web.StreamResponse: userdata = await self._userdata_from_rest_request(request) if not userdata: web_userdata = await self._userdata_from_web_request(request) if web_userdata: return web.HTTPUnauthorized(reason="provided web auth to REST endpoint") raise web.HTTPUnauthorized() - return await fun(request, userdata, *args, **kwargs) + return await fun(request, userdata) return wrapped - def web_authenticated_users_only(self, redirect=True): - def wrap(fun): + def web_authenticated_users_only( + self, redirect: bool = True + ) -> Callable[[AuthenticatedAIOHTTPHandler], AIOHTTPHandler]: + def wrap(fun: AuthenticatedAIOHTTPHandler): @wraps(fun) - async def wrapped(request, *args, **kwargs): + async def wrapped(request: web.Request) -> web.StreamResponse: userdata = await self._userdata_from_web_request(request) if not userdata: rest_userdata = await self._userdata_from_rest_request(request) if rest_userdata: - return web.HTTPUnauthorized(reason="provided REST auth to web endpoint") + raise web.HTTPUnauthorized(reason="provided REST auth to web endpoint") raise _web_unauthenticated(request, redirect) - return await fun(request, userdata, *args, **kwargs) + return await fun(request, userdata) return wrapped return wrap - def web_maybe_authenticated_user(self, fun): + def web_maybe_authenticated_user(self, fun: MaybeAuthenticatedAIOHTTPHandler) -> AIOHTTPHandler: @wraps(fun) - async def wrapped(request, *args, **kwargs): - return await fun(request, await self._userdata_from_web_request(request), *args, **kwargs) + async def wrapped(request: web.Request) -> web.StreamResponse: + return await fun(request, await self._userdata_from_web_request(request)) return wrapped @@ -100,7 +116,7 @@ async def _userdata_from_web_request(self, request): return await self._userdata_cache.lookup((session['session_id'], request.app['client_session'])) - async def _userdata_from_rest_request(self, request): + async def _userdata_from_rest_request(self, request: web.Request) -> Optional[UserData]: if 'Authorization' not in request.headers: return None auth_header = request.headers['Authorization'] @@ -138,7 +154,7 @@ async def impersonate_user_and_get_info(session_id: str, client_session: httpx.C def _web_unauthenticated(request, redirect): if not redirect: - return web.HTTPUnauthorized() + raise web.HTTPUnauthorized() login_url = deploy_config.external_url('auth', '/login') diff --git a/gear/gear/auth_utils.py b/gear/gear/auth_utils.py index 6c17c6173d5..69dfa00e343 100644 --- a/gear/gear/auth_utils.py +++ b/gear/gear/auth_utils.py @@ -1,7 +1,10 @@ import secrets +from typing import Optional from hailtop.auth import session_id_encode_to_str +from .database import Database + async def insert_user(db, spec): assert all(k in spec for k in ('state', 'username')) @@ -16,7 +19,7 @@ async def insert_user(db, spec): # 2592000s = 30d -async def create_session(db, user_id, max_age_secs=2592000): +async def create_session(db: Database, user_id: str, max_age_secs: Optional[int] = 2592000) -> str: session_id = session_id_encode_to_str(secrets.token_bytes(32)) await db.just_execute( 'INSERT INTO sessions (session_id, user_id, max_age_secs) VALUES (%s, %s, %s);', diff --git a/web_common/web_common/web_common.py b/web_common/web_common/web_common.py index 7ec41e6b81b..c5da5c98242 100644 --- a/web_common/web_common/web_common.py +++ b/web_common/web_common/web_common.py @@ -1,13 +1,14 @@ import importlib import os +from typing import Any, Dict, Optional -import aiohttp import aiohttp_jinja2 import aiohttp_session import jinja2 import sass +from aiohttp import web -from gear import new_csrf_token +from gear import UserData, new_csrf_token from hailtop.config import get_deploy_config deploy_config = get_deploy_config() @@ -29,7 +30,7 @@ def sass_compile(module_name): sass.compile(dirname=(scss_path, css_path), output_style='compressed', include_paths=[f'{WEB_COMMON_ROOT}/styles']) -def setup_aiohttp_jinja2(app: aiohttp.web.Application, module: str, *extra_loaders: jinja2.BaseLoader): +def setup_aiohttp_jinja2(app: web.Application, module: str, *extra_loaders: jinja2.BaseLoader): aiohttp_jinja2.setup( app, loader=jinja2.ChoiceLoader([jinja2.PackageLoader('web_common'), jinja2.PackageLoader(module), *extra_loaders]), @@ -74,7 +75,9 @@ def base_context(session, userdata, service): return context -async def render_template(service, request, userdata, file, page_context): +async def render_template( + service: str, request: web.Request, userdata: Optional[UserData], file: str, page_context: Dict[str, Any] +) -> web.Response: if '_csrf' in request.cookies: csrf_token = request.cookies['_csrf'] else: From 5e1df2e4a7d5e2851c70d22e600e562339f76fb4 Mon Sep 17 00:00:00 2001 From: jigold Date: Wed, 2 Aug 2023 15:49:19 -0400 Subject: [PATCH 056/180] [batch] Compact aggregated_billing_*_resources_v3 tables periodically (#13213) --- batch/batch/driver/main.py | 142 +++++++++++++++++++++++++- batch/sql/add-billing-index-token.sql | 2 + batch/sql/estimated-current.sql | 2 + build.yaml | 3 + 4 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 batch/sql/add-billing-index-token.sql diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 8588d47d7bc..7d3d066a272 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -26,6 +26,7 @@ AuthClient, Database, K8sCache, + Transaction, check_csrf_token, json_request, json_response, @@ -1367,15 +1368,148 @@ async def monitor_system(app): monitor_instances(app) -async def compact_agg_billing_project_users_table(app): +async def compact_agg_billing_project_users_table(app, db: Database): if not app['feature_flags']['compact_billing_tables']: return + @transaction(db) + async def compact(tx: Transaction, target: dict): + original_usage = await tx.execute_and_fetchone( + ''' +SELECT CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` +FROM aggregated_billing_project_user_resources_v3 +WHERE billing_project = %s AND `user` = %s AND resource_id = %s +FOR UPDATE; +''', + (target['billing_project'], target['user'], target['resource_id']), + ) + + await tx.just_execute( + ''' +DELETE FROM aggregated_billing_project_user_resources_v3 +WHERE billing_project = %s AND `user` = %s AND resource_id = %s; +''', + (target['billing_project'], target['user'], target['resource_id']), + ) + + await tx.execute_update( + ''' +INSERT INTO aggregated_billing_project_user_resources_v3 (billing_project, `user`, resource_id, token, `usage`) +VALUES (%s, %s, %s, %s, %s); +''', + ( + target['billing_project'], + target['user'], + target['resource_id'], + 0, + original_usage['usage'], + ), + ) + + new_usage = await tx.execute_and_fetchone( + ''' +SELECT CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` +FROM aggregated_billing_project_user_resources_v3 +WHERE billing_project = %s AND `user` = %s AND resource_id = %s +GROUP BY billing_project, `user`, resource_id; +''', + (target['billing_project'], target['user'], target['resource_id']), + ) + + if new_usage['usage'] != original_usage['usage']: + raise ValueError( + f'problem in audit for {target}. original usage = {original_usage} but new usage is {new_usage}. aborting' + ) + + targets = db.execute_and_fetchall( + ''' +SELECT billing_project, `user`, resource_id, COUNT(*) AS n_tokens +FROM aggregated_billing_project_user_resources_v3 +WHERE token != 0 +GROUP BY billing_project, `user`, resource_id +ORDER BY n_tokens DESC +LIMIT 10000; +''', + query_name='find_agg_billing_project_user_resource_to_compact', + ) + + targets = [target async for target in targets] + + for target in targets: + await compact(target) # pylint: disable=no-value-for-parameter + -async def compact_agg_billing_project_users_by_date_table(app): +async def compact_agg_billing_project_users_by_date_table(app, db: Database): if not app['feature_flags']['compact_billing_tables']: return + @transaction(db) + async def compact(tx: Transaction, target: dict): + original_usage = await tx.execute_and_fetchone( + ''' +SELECT CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` +FROM aggregated_billing_project_user_resources_by_date_v3 +WHERE billing_date = %s AND billing_project = %s AND `user` = %s AND resource_id = %s +FOR UPDATE; +''', + (target['billing_date'], target['billing_project'], target['user'], target['resource_id']), + ) + + await tx.just_execute( + ''' +DELETE FROM aggregated_billing_project_user_resources_by_date_v3 +WHERE billing_date = %s AND billing_project = %s AND `user` = %s AND resource_id = %s; +''', + (target['billing_date'], target['billing_project'], target['user'], target['resource_id']), + ) + + await tx.execute_update( + ''' +INSERT INTO aggregated_billing_project_user_resources_by_date_v3 (billing_date, billing_project, `user`, resource_id, token, `usage`) +VALUES (%s, %s, %s, %s, %s, %s); +''', + ( + target['billing_date'], + target['billing_project'], + target['user'], + target['resource_id'], + 0, + original_usage['usage'], + ), + ) + + new_usage = await tx.execute_and_fetchone( + ''' +SELECT CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` +FROM aggregated_billing_project_user_resources_by_date_v3 +WHERE billing_date = %s AND billing_project = %s AND `user` = %s AND resource_id = %s +GROUP BY billing_date, billing_project, `user`, resource_id; +''', + (target['billing_date'], target['billing_project'], target['user'], target['resource_id']), + ) + + if new_usage['usage'] != original_usage['usage']: + raise ValueError( + f'problem in audit for {target}. original usage = {original_usage} but new usage is {new_usage}. aborting' + ) + + targets = db.execute_and_fetchall( + ''' +SELECT billing_date, billing_project, `user`, resource_id, COUNT(*) AS n_tokens +FROM aggregated_billing_project_user_resources_by_date_v3 +WHERE token != 0 +GROUP BY billing_date, billing_project, `user`, resource_id +ORDER BY n_tokens DESC +LIMIT 10000; +''', + query_name='find_agg_billing_project_user_resource_by_date_to_compact', + ) + + targets = [target async for target in targets] + + for target in targets: + await compact(target) # pylint: disable=no-value-for-parameter + async def scheduling_cancelling_bump(app): log.info('scheduling cancelling bump loop') @@ -1482,8 +1616,8 @@ async def on_startup(app): task_manager.ensure_future(periodically_call(60, scheduling_cancelling_bump, app)) task_manager.ensure_future(periodically_call(15, monitor_system, app)) task_manager.ensure_future(periodically_call(5, refresh_globals_from_db, app, db)) - task_manager.ensure_future(periodically_call(60, compact_agg_billing_project_users_table, app)) - task_manager.ensure_future(periodically_call(60, compact_agg_billing_project_users_by_date_table, app)) + task_manager.ensure_future(periodically_call(60, compact_agg_billing_project_users_table, app, db)) + task_manager.ensure_future(periodically_call(60, compact_agg_billing_project_users_by_date_table, app, db)) async def on_cleanup(app): diff --git a/batch/sql/add-billing-index-token.sql b/batch/sql/add-billing-index-token.sql new file mode 100644 index 00000000000..28d4ae8ba4d --- /dev/null +++ b/batch/sql/add-billing-index-token.sql @@ -0,0 +1,2 @@ +CREATE INDEX aggregated_billing_project_user_resources_v3_token ON `aggregated_billing_project_user_resources_v3` (`token`); +CREATE INDEX aggregated_billing_project_user_resources_by_date_v3_token ON `aggregated_billing_project_user_resources_by_date_v3` (`token`); diff --git a/batch/sql/estimated-current.sql b/batch/sql/estimated-current.sql index 423a2be8035..6a0a97c9044 100644 --- a/batch/sql/estimated-current.sql +++ b/batch/sql/estimated-current.sql @@ -424,6 +424,7 @@ CREATE TABLE IF NOT EXISTS `aggregated_billing_project_user_resources_v3` ( FOREIGN KEY (`resource_id`) REFERENCES resources(`resource_id`) ON DELETE CASCADE ) ENGINE = InnoDB; CREATE INDEX aggregated_billing_project_user_resources_v3 ON `aggregated_billing_project_user_resources_v3` (`user`); +CREATE INDEX aggregated_billing_project_user_resources_v3_token ON `aggregated_billing_project_user_resources_v3` (`token`); CREATE TABLE IF NOT EXISTS `aggregated_billing_project_user_resources_by_date_v3` ( `billing_date` DATE NOT NULL, @@ -437,6 +438,7 @@ CREATE TABLE IF NOT EXISTS `aggregated_billing_project_user_resources_by_date_v3 FOREIGN KEY (`resource_id`) REFERENCES resources(`resource_id`) ON DELETE CASCADE ) ENGINE = InnoDB; CREATE INDEX aggregated_billing_project_user_resources_by_date_v3_user ON `aggregated_billing_project_user_resources_by_date_v3` (`billing_date`, `user`); +CREATE INDEX aggregated_billing_project_user_resources_by_date_v3_token ON `aggregated_billing_project_user_resources_by_date_v3` (`token`); CREATE TABLE IF NOT EXISTS `aggregated_batch_resources_v3` ( `batch_id` BIGINT NOT NULL, diff --git a/build.yaml b/build.yaml index 6089bd70eaf..80175433f27 100644 --- a/build.yaml +++ b/build.yaml @@ -2289,6 +2289,9 @@ steps: - name: turn_off_oms_agent_test_dev script: /io/sql/turn_off_oms_agent_test_dev.py online: true + - name: add-billing-index-token + script: /io/sql/add-billing-index-token.sql + online: true inputs: - from: /repo/batch/sql to: /io/sql From 4da70e27566ffd54c26bae08ebc3f1723809e755 Mon Sep 17 00:00:00 2001 From: Dan King Date: Wed, 2 Aug 2023 17:01:40 -0400 Subject: [PATCH 057/180] [fs] do not unlink the directory if there was an exception (#13362) I created this bug when I added exception handling. I incorrectly put the exception handling *after* the `rmdir`. If an exception occurred while removing one of the children of a directory, in all likelihood, the directory is non-empty. With this change, we raise any exceptions before unlinking the directory. It is the responsibility of the caller to decide what to do if we were unable to remove one of our children. I saw this while debugging another transient error on another PR: https://github.com/hail-is/hail/issues/13361. --- hail/python/hailtop/aiotools/local_fs.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hail/python/hailtop/aiotools/local_fs.py b/hail/python/hailtop/aiotools/local_fs.py index 52655c49c02..58f51d6aabd 100644 --- a/hail/python/hailtop/aiotools/local_fs.py +++ b/hail/python/hailtop/aiotools/local_fs.py @@ -374,10 +374,7 @@ async def rm_dir(pool: OnlineBoundedGather2, listener(1) if contents_tasks: await pool.wait(contents_tasks) - try: - await self.rmdir(path) - listener(-1) - finally: + def raise_them_all(exceptions: List[BaseException]): if exceptions: try: @@ -389,6 +386,8 @@ def raise_them_all(exceptions: List[BaseException]): for exc in [t.exception()] if exc is not None] raise_them_all(excs) + await self.rmdir(path) + listener(-1) async with OnlineBoundedGather2(sema) as pool: contents_tasks_by_dir: Dict[str, List[asyncio.Task]] = {} From 763f4319b4fc3b6a7bf5ceed754aab0b83614994 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 2 Aug 2023 18:15:01 -0400 Subject: [PATCH 058/180] [ci] Remove unnecessary worker-deploy-config secret (#13343) Since #13211, all jobs by default have a deploy config mounted into the container. The `worker-deploy-config` secret is no longer necessary, so long as we properly configure the namespace that CI jobs need to talk to. --- build.yaml | 106 ++++-------------- ci/test/resources/build.yaml | 5 - .../scala/is/hail/services/DeployConfig.scala | 18 ++- 3 files changed, 34 insertions(+), 95 deletions(-) diff --git a/build.yaml b/build.yaml index 80175433f27..9211c73b8ac 100644 --- a/build.yaml +++ b/build.yaml @@ -416,15 +416,6 @@ steps: --from-file=./deploy-config.json \ --save-config --dry-run=client -o yaml \ | kubectl -n {{ default_ns.name }} apply -f - - - # worker deploy config - cat > deploy-config.json < create-billing-projects.py <cancel_all_running_test_batches.py <<'EOF' from hailtop.batch_client.aioclient import BatchClient import asyncio @@ -3697,10 +3640,6 @@ steps: python3 cancel_all_running_test_batches.py secrets: - - name: worker-deploy-config - namespace: - valueFrom: default_ns.name - mountPath: /deploy-config - name: test-dev-tokens namespace: valueFrom: default_ns.name @@ -3726,6 +3665,7 @@ steps: image: valueFrom: hail_dev_image.image script: | + export HAIL_DEFAULT_NAMESPACE={{ default_ns.name }} export DOCKER_PREFIX="{{ global.docker_prefix }}" export DOCKER_ROOT_IMAGE="{{ global.docker_root_image }}" python3 -m pytest \ @@ -3745,10 +3685,6 @@ steps: to: /io/test timeout: 300 secrets: - - name: worker-deploy-config - namespace: - valueFrom: default_ns.name - mountPath: /deploy-config - name: test-dev-tokens namespace: valueFrom: default_ns.name diff --git a/ci/test/resources/build.yaml b/ci/test/resources/build.yaml index b625c8b2167..448c9b774b5 100644 --- a/ci/test/resources/build.yaml +++ b/ci/test/resources/build.yaml @@ -280,7 +280,6 @@ steps: valueFrom: ci_utils_image.image script: | set -ex - export HAIL_DEPLOY_CONFIG_FILE=/deploy-config/deploy-config.json hailctl curl {{ default_ns.name }} \ hello /healthcheck \ -fsSL \ @@ -292,10 +291,6 @@ steps: namespace: valueFrom: default_ns.name mountPath: /user-tokens - - name: worker-deploy-config - namespace: - valueFrom: default_ns.name - mountPath: /deploy-config dependsOn: - ci_utils_image - default_ns diff --git a/hail/src/main/scala/is/hail/services/DeployConfig.scala b/hail/src/main/scala/is/hail/services/DeployConfig.scala index 589642edf5d..e05462e7879 100644 --- a/hail/src/main/scala/is/hail/services/DeployConfig.scala +++ b/hail/src/main/scala/is/hail/services/DeployConfig.scala @@ -52,19 +52,27 @@ object DeployConfig { fromConfig(JsonMethods.parse(in)) } } else - new DeployConfig( - "external", - "default", - "hail.is") + fromConfig("external", "default", "hail.is") } def fromConfig(config: JValue): DeployConfig = { implicit val formats: Formats = DefaultFormats - new DeployConfig( + fromConfig( (config \ "location").extract[String], (config \ "default_namespace").extract[String], (config \ "domain").extract[Option[String]].getOrElse("hail.is")) } + + def fromConfig(location: String, defaultNamespace: String, domain: String): DeployConfig = { + new DeployConfig( + sys.env.getOrElse(toEnvVarName("location"), location), + sys.env.getOrElse(toEnvVarName("default_namespace"), defaultNamespace), + sys.env.getOrElse(toEnvVarName("domain"), domain)) + } + + private[this] def toEnvVarName(s: String): String = { + "HAIL_" + s.toUpperCase + } } class DeployConfig( From d3ac1c45364c998b2d241adf1c5015977eeb0951 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Wed, 2 Aug 2023 19:32:12 -0400 Subject: [PATCH 059/180] [query] Add file info to Tabix VCF read exception (#13342) --- .../is/hail/io/vcf/TabixReadVCFIterator.scala | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala b/hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala index fe260729212..51d8939131d 100644 --- a/hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala +++ b/hail/src/main/scala/is/hail/io/vcf/TabixReadVCFIterator.scala @@ -36,25 +36,33 @@ class TabixReadVCFIterator(fs: FS, file: String, contigMapping: Map[String, Stri def next(): GenericLine = { assert(l != null) - val n = l - val idx = curIdx - l = lines.next() - curIdx = lines.getCurIdx() - if (l == null) - lines.close() - val bytes = n.getBytes - new GenericLine(file, 0, idx, bytes, bytes.length) + try { + val n = l + val idx = curIdx + l = lines.next() + curIdx = lines.getCurIdx() + if (l == null) + lines.close() + val bytes = n.getBytes + new GenericLine(file, 0, idx, bytes, bytes.length) + } catch { + case e: Exception => fatal(s"error reading file: $file at ${ lines.getCurIdx() }", e) + } } }.filter { gl => val s = gl.toString val t1 = s.indexOf('\t') val t2 = s.indexOf('\t', t1 + 1) + if (t1 == -1 || t2 == -1) { + fatal(s"invalid line in file ${ gl.file } no CHROM or POS column at offset ${ gl.offset }.\n$s") + } + val chr = s.substring(0, t1) val pos = s.substring(t1 + 1, t2).toInt if (chr != chrom) { - throw new RuntimeException(s"bad chromosome! ${ chrom }, $s") + fatal(s"in file ${ gl.file } at offset ${ gl.offset }, bad chromosome! ${ chrom }, $s") } start <= pos && pos <= end } @@ -112,4 +120,3 @@ class TabixReadVCFIterator(fs: FS, file: String, contigMapping: Map[String, Stri linesIter.close() } } - From 00c5701ca3cd6b7f7416f66851fd5f40d2e2c872 Mon Sep 17 00:00:00 2001 From: Dan King Date: Wed, 2 Aug 2023 20:40:24 -0400 Subject: [PATCH 060/180] [fs] add debugging information to flaky test_hadoop_methods_3 (#13363) See https://github.com/hail-is/hail/issues/13361 for details. Something goes wrong when cleaning up after this test. --- hail/python/test/hail/utils/test_hl_hadoop_and_hail_fs.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hail/python/test/hail/utils/test_hl_hadoop_and_hail_fs.py b/hail/python/test/hail/utils/test_hl_hadoop_and_hail_fs.py index 864345178df..686bb24e7fd 100644 --- a/hail/python/test/hail/utils/test_hl_hadoop_and_hail_fs.py +++ b/hail/python/test/hail/utils/test_hl_hadoop_and_hail_fs.py @@ -6,7 +6,7 @@ import hail as hl import hailtop.fs as fs from hail.context import _get_local_tmpdir -from hail.utils import hadoop_open, hadoop_copy +from hail.utils import hadoop_open, hadoop_copy, hadoop_ls from hailtop.utils import secret_alnum_string from hail.utils.java import FatalError @@ -76,6 +76,8 @@ def test_hadoop_methods_3(tmpdir: str): assert data == data4 + print(f'contents of my tmpdir, {tmpdir}:') + print(repr(hadoop_ls(tmpdir))) def test_read_overwrite(tmpdir): with fs.open(os.path.join(tmpdir, 'randomBytes'), 'wb') as f: From 36fef80a238efb24cd10439dc23372892cb05e5f Mon Sep 17 00:00:00 2001 From: Dan King Date: Wed, 2 Aug 2023 21:47:13 -0400 Subject: [PATCH 061/180] [query] ensure functions need by DSP are not moved (#13369) https://hail.zulipchat.com/#narrow/stream/379853-Hail.2FVariants/topic/handing.20off.20import_gvs/near/381266567 --- .../test_dsp_necessary_functions_have_not_moved.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 hail/python/test/hail/experimental/test_dsp_necessary_functions_have_not_moved.py diff --git a/hail/python/test/hail/experimental/test_dsp_necessary_functions_have_not_moved.py b/hail/python/test/hail/experimental/test_dsp_necessary_functions_have_not_moved.py new file mode 100644 index 00000000000..02837d071a2 --- /dev/null +++ b/hail/python/test/hail/experimental/test_dsp_necessary_functions_have_not_moved.py @@ -0,0 +1,9 @@ +import hail as hl + + +def test_dsp_used_functions_have_not_moved(): + # DSP's variants team depends on these functions which are in experimental. Normally we do not + # guarantee backwards compatibility but given the practical importance of these to production + # pipelines at Broad, we ensure they continue to exist. + + assert hl.experimental.full_outer_join_mt is not None From 8421b18b714b815cccd7967b3e2d125cad46a4c2 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Thu, 3 Aug 2023 10:08:07 -0400 Subject: [PATCH 062/180] [query/combiner] Fix import_gvcf_interval's default PGT handling (#13364) PGT is a call field by default for import_vcf, the now former import_gvcfs (old combiner start point). Make import_gvcf_interval also treat PGT as a call field. --- hail/python/hail/methods/impex.py | 2 +- hail/python/test/hail/vds/test_combiner.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hail/python/hail/methods/impex.py b/hail/python/hail/methods/impex.py index 3eaf1feedf4..9dc23f031e3 100644 --- a/hail/python/hail/methods/impex.py +++ b/hail/python/hail/methods/impex.py @@ -2837,7 +2837,7 @@ def import_vcf(path, filter=nullable(str), find=nullable(str), replace=nullable(str)) -def import_gvcf_interval(path, file_num, contig, start, end, header_info, call_fields=[], entry_float_type='float64', +def import_gvcf_interval(path, file_num, contig, start, end, header_info, call_fields=['PGT'], entry_float_type='float64', array_elements_required=True, reference_genome='default', contig_recoding=None, skip_invalid_loci=False, filter=None, find=None, replace=None): indices, aggs = hl.expr.unify_all(path, file_num, contig, start, end) diff --git a/hail/python/test/hail/vds/test_combiner.py b/hail/python/test/hail/vds/test_combiner.py index a91c4a560c7..bb3651007e7 100644 --- a/hail/python/test/hail/vds/test_combiner.py +++ b/hail/python/test/hail/vds/test_combiner.py @@ -39,6 +39,11 @@ def test_combiner_works(): out = os.path.join(tmpdir, 'out.vds') hl.vds.new_combiner(temp_path=tmpdir, output_path=out, gvcf_paths=paths, intervals=parts, reference_genome='GRCh38').run() comb = hl.vds.read_vds(out) + + # see https://github.com/hail-is/hail/issues/13367 for why these assertions are here + assert 'LPGT' in comb.variant_data.entry + assert comb.variant_data.LPGT.dtype == hl.tcall + assert len(parts) == comb.variant_data.n_partitions() comb.variant_data._force_count_rows() comb.reference_data._force_count_rows() From 6921e6c138e3f67600fdcf3df482f9b1eaf91b6b Mon Sep 17 00:00:00 2001 From: John Marshall Date: Fri, 4 Aug 2023 03:48:49 +1200 Subject: [PATCH 063/180] Replace invocations of some deprecated Hail functions with their replacements [minor] (#13349) Rewrite invocations of `hl.cond()` to `hl.if_else()`, `hl.null()` to `hl.missing()`, and `hl.zip_with_index()` to `hl.enumerate()`. Very minor, but a few of these appear in our test logs (and probably yours as well), which makes for noise when you're tracking down other problems in the logs: ``` hail/methods/misc.py:437: DeprecationWarning: Call to deprecated function (or staticmethod) cond. (Replaced by hl.if_else) -- Deprecated since version 0.2.59. hail/vds/methods.py:79: DeprecationWarning: Call to deprecated function (or staticmethod) zip_with_index. (Replaced by hl.enumerate) -- Deprecated since version 0.2.56. hail/vds/methods.py:75: DeprecationWarning: Call to deprecated function (or staticmethod) null. (Replaced by hl.missing) -- Deprecated since version 0.2.62. ``` --- .../python/benchmark_hail/run/matrix_table_benchmarks.py | 2 +- datasets/load/load.1000_Genomes_phase3_relationships.py | 6 +++--- datasets/load/load.DANN.py | 2 +- datasets/load/load.GTEx_v7_RNA_seq.py | 2 +- datasets/load/load.LDSC_baseline_v1.1_bed_files.py | 2 +- hail/python/hail/methods/misc.py | 2 +- hail/python/hail/vds/methods.py | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/benchmark/python/benchmark_hail/run/matrix_table_benchmarks.py b/benchmark/python/benchmark_hail/run/matrix_table_benchmarks.py index b5df2630a4b..85dfdb3b9c5 100644 --- a/benchmark/python/benchmark_hail/run/matrix_table_benchmarks.py +++ b/benchmark/python/benchmark_hail/run/matrix_table_benchmarks.py @@ -321,7 +321,7 @@ def large_range_matrix_table_sum(): @benchmark(args=profile_25.handle('mt')) def kyle_sex_specific_qc(mt_path): mt = hl.read_matrix_table(mt_path) - mt = mt.annotate_cols(sex=hl.cond(hl.rand_bool(0.5), 'Male', 'Female')) + mt = mt.annotate_cols(sex=hl.if_else(hl.rand_bool(0.5), 'Male', 'Female')) (num_males, num_females) = mt.aggregate_cols((hl.agg.count_where(mt.sex == 'Male'), hl.agg.count_where(mt.sex == 'Female'))) mt = mt.annotate_rows( diff --git a/datasets/load/load.1000_Genomes_phase3_relationships.py b/datasets/load/load.1000_Genomes_phase3_relationships.py index 666d1fca885..9a7dff4595d 100644 --- a/datasets/load/load.1000_Genomes_phase3_relationships.py +++ b/datasets/load/load.1000_Genomes_phase3_relationships.py @@ -17,9 +17,9 @@ ht_relationships['paternal_id']), maternal_id=hl.or_missing(ht_relationships['maternal_id'] != '0', ht_relationships['maternal_id']), - relationship_role=hl.cond(ht_relationships['relationship_role'] == 'unrel', - 'unrelated', - ht_relationships['relationship_role']), + relationship_role=hl.if_else(ht_relationships['relationship_role'] == 'unrel', + 'unrelated', + ht_relationships['relationship_role']), sibling_ids=hl.or_missing(ht_relationships['sibling_ids'] == '0', hl.map(lambda x: x.strip(), ht_relationships['sibling_ids'].split(','))), children_ids=hl.or_missing(ht_relationships['children_ids'] == '0', diff --git a/datasets/load/load.DANN.py b/datasets/load/load.DANN.py index 026127dcf16..59087718df0 100644 --- a/datasets/load/load.DANN.py +++ b/datasets/load/load.DANN.py @@ -33,7 +33,7 @@ ht = ht.select('score') ht = ht.annotate_globals(metadata=hl.struct(name=name, - version=hl.null(hl.tstr), + version=hl.missing(hl.tstr), reference_genome=build, n_rows=n_rows, n_partitions=n_partitions)) diff --git a/datasets/load/load.GTEx_v7_RNA_seq.py b/datasets/load/load.GTEx_v7_RNA_seq.py index b1dba968f95..98b1cc1414a 100644 --- a/datasets/load/load.GTEx_v7_RNA_seq.py +++ b/datasets/load/load.GTEx_v7_RNA_seq.py @@ -28,7 +28,7 @@ .when(ht_subjects['DTHHRDY'] == '2', '2_fast_death_of_natural_causes') .when(ht_subjects['DTHHRDY'] == '3', '3_intermediate_death') .when(ht_subjects['DTHHRDY'] == '4', '4_slow_death') - .default(hl.null(hl.tstr)))) + .default(hl.missing(hl.tstr)))) ht_subjects = ht_subjects.select('is_female', 'age_range', 'death_classification_hardy_scale') ht_subjects.write('hdfs:///tmp/subjects.ht', overwrite=True) ht_subjects = hl.read_table('hdfs:///tmp/subjects.ht') diff --git a/datasets/load/load.LDSC_baseline_v1.1_bed_files.py b/datasets/load/load.LDSC_baseline_v1.1_bed_files.py index 5df094df5c7..7e4f7e49c3e 100644 --- a/datasets/load/load.LDSC_baseline_v1.1_bed_files.py +++ b/datasets/load/load.LDSC_baseline_v1.1_bed_files.py @@ -95,7 +95,7 @@ def locus_interval_expr(contig, start, end, includes_start, includes_end, ht = ht.annotate(interval=hl.locus_interval( contig=ht.f0.replace('chr', ''), start=ht.f1 + 1, - end=hl.cond(end > length, length, end)), + end=hl.if_else(end > length, length, end)), includes_start=True, includes_end=True, reference_genome='GRCh37')) diff --git a/hail/python/hail/methods/misc.py b/hail/python/hail/methods/misc.py index a74bc04d089..819d335bdde 100644 --- a/hail/python/hail/methods/misc.py +++ b/hail/python/hail/methods/misc.py @@ -434,7 +434,7 @@ def segment_intervals(ht, points): lower = hl.if_else((lower < n_points) & (points[lower] == interval.start), lower + 1, lower) higher = hl.if_else((higher < n_points) & (points[higher] == interval.end), higher - 1, higher) interval_results = hl.rbind(lower, higher, - lambda lower, higher: hl.cond( + lambda lower, higher: hl.if_else( lower >= higher, [interval], hl.flatten([ diff --git a/hail/python/hail/vds/methods.py b/hail/python/hail/vds/methods.py index c80c950a00a..320de78c0d6 100644 --- a/hail/python/hail/vds/methods.py +++ b/hail/python/hail/vds/methods.py @@ -72,11 +72,11 @@ def coalesce_join(ref, var): return hl.if_else(hl.is_defined(var), var.select(*shared_fields, *var_fields), ref.annotate(**{call_field: hl.call(0, 0)}) - .select(*shared_fields, **{f: hl.null(var[f].dtype) for f in var_fields})) + .select(*shared_fields, **{f: hl.missing(var[f].dtype) for f in var_fields})) dr = dr.annotate( _dense=hl.rbind(dr._ref_entries, - lambda refs_at_this_row: hl.zip_with_index(hl.zip(dr._var_entries, dr.dense_ref)).map( + lambda refs_at_this_row: hl.enumerate(hl.zip(dr._var_entries, dr.dense_ref)).map( lambda tup: coalesce_join(hl.coalesce(refs_at_this_row[tup[0]], hl.or_missing(tup[1][1]._END_GLOBAL >= dr.locus.global_position(), tup[1][1])), tup[1][0]) @@ -1125,7 +1125,7 @@ def keep_last(t1, t2): t2) # approximate a scan that merges before result - ht = ht.annotate(prev_block=hl.zip(hl.scan.array_agg(lambda elt: hl.scan.fold((hl.null(rd.entry.dtype), False), + ht = ht.annotate(prev_block=hl.zip(hl.scan.array_agg(lambda elt: hl.scan.fold((hl.missing(rd.entry.dtype), False), lambda acc: keep_last(acc, ( elt, False)), keep_last), ht.entries), ht.entries) From 9f481ce22f1cf516e28bba0aa042262c6dc2387c Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Thu, 3 Aug 2023 13:28:27 -0400 Subject: [PATCH 064/180] [query/vds] Teach read_vds to supress the 'no ref block max length warning' (#13360) Use it in the combiner as it's very noisy otherwise. --- .../hail/vds/combiner/variant_dataset_combiner.py | 11 +++++++---- hail/python/hail/vds/variant_dataset.py | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hail/python/hail/vds/combiner/variant_dataset_combiner.py b/hail/python/hail/vds/combiner/variant_dataset_combiner.py index d45c82e5a4a..cc59379bf58 100644 --- a/hail/python/hail/vds/combiner/variant_dataset_combiner.py +++ b/hail/python/hail/vds/combiner/variant_dataset_combiner.py @@ -432,7 +432,8 @@ def _step_vdses(self): largest_vds = max(files_to_merge, key=lambda vds: vds.n_samples) vds = hl.vds.read_vds(largest_vds.path, _assert_reference_type=self._dataset_type.reference_type, - _assert_variant_type=self._dataset_type.variant_type) + _assert_variant_type=self._dataset_type.variant_type, + _warn_no_ref_block_max_length=False) interval_bin = floor(log(new_n_samples, self._branch_factor)) intervals = self.__intervals_cache.get(interval_bin) @@ -569,7 +570,8 @@ def _read_variant_datasets(self, inputs: List[str], intervals: List[Interval]): variant_type = self._dataset_type.variant_type return [hl.vds.read_vds(path, intervals=intervals, _assert_reference_type=reference_type, - _assert_variant_type=variant_type) + _assert_variant_type=variant_type, + _warn_no_ref_block_max_length=False) for path in inputs] @@ -692,7 +694,7 @@ def maybe_load_from_saved_path(save_path: str) -> Optional[VariantDatasetCombine vds = None gvcf_type = None if vds_paths: - vds = hl.vds.read_vds(vds_paths[0]) + vds = hl.vds.read_vds(vds_paths[0], _warn_no_ref_block_max_length=False) ref_entry_tmp = set(vds.reference_data.entry) - {'END'} if gvcf_reference_entry_fields_to_keep is not None and ref_entry_tmp != gvcf_reference_entry_fields_to_keep: warning("Mismatch between 'gvcf_reference_entry_fields' to keep and VDS reference data " @@ -757,7 +759,8 @@ def maybe_load_from_saved_path(save_path: str) -> Optional[VariantDatasetCombine vdses = [] for path in vds_paths: vds = hl.vds.read_vds(path, _assert_reference_type=dataset_type.reference_type, - _assert_variant_type=dataset_type.variant_type) + _assert_variant_type=dataset_type.variant_type, + _warn_no_ref_block_max_length=False) n_samples = vds.n_samples() vdses.append(VDSMetadata(path, n_samples)) diff --git a/hail/python/hail/vds/variant_dataset.py b/hail/python/hail/vds/variant_dataset.py index 6a214a7d4a2..388897298d3 100644 --- a/hail/python/hail/vds/variant_dataset.py +++ b/hail/python/hail/vds/variant_dataset.py @@ -12,7 +12,8 @@ def read_vds(path, *, intervals=None, n_partitions=None, - _assert_reference_type=None, _assert_variant_type=None) -> 'VariantDataset': + _assert_reference_type=None, _assert_variant_type=None, + _warn_no_ref_block_max_length=True) -> 'VariantDataset': """Read in a :class:`.VariantDataset` written with :meth:`.VariantDataset.write`. Parameters @@ -42,7 +43,7 @@ def read_vds(path, *, intervals=None, n_partitions=None, with fs.open(metadata_file, 'r') as f: metadata = json.load(f) vds.reference_data = vds.reference_data.annotate_globals(**metadata) - else: + elif _warn_no_ref_block_max_length: warning("You are reading a VDS written with an older version of Hail." "\n Hail now supports much faster interval filters on VDS, but you'll need to run either" "\n `hl.vds.truncate_reference_blocks(vds, ...)` and write a copy (see docs) or patch the" From 33883599645a2ec619e4769a349c3993eedd2210 Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Thu, 3 Aug 2023 14:39:17 -0400 Subject: [PATCH 065/180] [query] allow inteval filters to work with indirect row key (#13333) E.g. when the row key, and/or the row itself, in a predicate is hidden behind Refs, MakeStructs, SelectFields. For example, before matching the first key field "kf" only worked for exactly `GetField(Ref("row", ...), "kf")`. Now the following all work (meaning the analysis recognizes these all as being the first key field): ``` Let("foo", SelectFields(Ref("row"), [..., "kf", ...]), GetField(Ref("foo"), "kf")) Let("foo", Ref("row"), Let("bar", MakeStruct("baz" -> GetField(Ref("foo"), "kf"), ...) GetField(Ref("bar"), "baz"))) ``` Edit: A note on how serious the issue was in practice: Any filter that uses more than one field (or the same field twice) was broken, where broken means it does no interval filter and reads all the data. E.g. `ht.filter((ht.locus >= hl.locus('20', 1)) & (ht.locus < hl.locus('20', 10200000)))`. This is because the repeated field is pulled out into a let by CSE. If it was two different fields, the underlying `Ref("row")` is pulled out. Other restrictions this PR doesn't address: * The predicate can't have a repeated sub-predicate, e.g. ``` subcond = ht.locus.contig == '20' ht.filter((subcond & (ht.locus.position < 10)) | (subcond & (ht.locus.position > 10200000))) ``` * The predicate can't use negation or `If` * The key type being filtered can only be Locus or numeric (or structs of those), doesn't work for e.g. gene Strings. --- .../hail/extract_intervals/test_key_prefix.py | 22 ++++++ .../hail/expr/ir/ExtractIntervalFilters.scala | 70 +++++++++++++++---- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/hail/python/test/hail/extract_intervals/test_key_prefix.py b/hail/python/test/hail/extract_intervals/test_key_prefix.py index 9d914970863..b42d38b5703 100644 --- a/hail/python/test/hail/extract_intervals/test_key_prefix.py +++ b/hail/python/test/hail/extract_intervals/test_key_prefix.py @@ -33,6 +33,14 @@ def test_mt_gt(mt, probe_locus): assert expr.count() == (100, 100) +def test_mt_ge_with_bindings(mt, probe_locus): + row = mt.row + locus = row.locus + expr = mt.filter_rows((locus >= probe_locus) & hl.is_defined(locus)) + assert expr.n_partitions() == 6 + assert expr.count() == (101, 100) + + def test_ht_lt(ht, probe_locus): expr = ht.filter(ht.locus < probe_locus) assert expr.n_partitions() == 15 @@ -99,3 +107,17 @@ def test_ht_gt(ht, probe_locus): expr = ht.filter(ht.locus > probe_locus) assert expr.n_partitions() == 6 assert expr.count() == 100 + + +def test_ht_ge_with_bindings(ht, probe_locus): + row = ht.row + locus = row.locus + expr = ht.filter((locus >= probe_locus) & hl.is_defined(locus)) + assert expr.n_partitions() == 6 + assert expr.count() == 101 + + +def test_GRCh38(): + mt = hl.balding_nichols_model(1, 10, 100, n_partitions=10, reference_genome='GRCh38') + mt = mt.filter_rows(hl.all(mt.locus.contig == 'chr1', mt.locus.position < 5)) + assert mt.n_partitions() == 1 diff --git a/hail/src/main/scala/is/hail/expr/ir/ExtractIntervalFilters.scala b/hail/src/main/scala/is/hail/expr/ir/ExtractIntervalFilters.scala index 2d9a9324a31..cc776386bb2 100644 --- a/hail/src/main/scala/is/hail/expr/ir/ExtractIntervalFilters.scala +++ b/hail/src/main/scala/is/hail/expr/ir/ExtractIntervalFilters.scala @@ -2,32 +2,77 @@ package is.hail.expr.ir import is.hail.backend.ExecuteContext import is.hail.annotations.IntervalEndpointOrdering +import is.hail.rvd.PartitionBoundOrdering import is.hail.types.virtual._ import is.hail.utils.{FastSeq, Interval, IntervalEndpoint, _} import is.hail.variant.{Locus, ReferenceGenome} import org.apache.spark.sql.Row +import scala.Option.option2Iterable + object ExtractIntervalFilters { val MAX_LITERAL_SIZE = 4096 - case class ExtractionState(ctx: ExecuteContext, rowRef: Ref, keyFields: IndexedSeq[String]) { + object ExtractionState { + def apply( + ctx: ExecuteContext, + rowRef: Ref, + keyFields: IndexedSeq[String] + ): ExtractionState = { + new ExtractionState(ctx, Env.empty[IR], rowRef, keyFields) + } + } + + class ExtractionState( + val ctx: ExecuteContext, + env: Env[IR], + rowRef: Ref, + keyFields: IndexedSeq[String] + ) { val rowType: TStruct = rowRef.typ.asInstanceOf[TStruct] val rowKeyType: TStruct = rowType.select(keyFields)._1 val firstKeyType: Type = rowKeyType.types.head - val iOrd: IntervalEndpointOrdering = rowKeyType.ordering(ctx.stateManager).intervalEndpointOrdering + val iOrd: IntervalEndpointOrdering = PartitionBoundOrdering(ctx, rowKeyType).intervalEndpointOrdering def getReferenceGenome(rg: String): ReferenceGenome = ctx.stateManager.referenceGenomes(rg) - def isFirstKey(ir: IR): Boolean = ir == GetField(rowRef, rowKeyType.fieldNames.head) + def bind(name: String, v: IR): ExtractionState = + new ExtractionState(ctx, env.bind(name, v), rowRef, keyFields) + + private def isRowRef(ir: IR): Boolean = ir match { + case ref: Ref => + ref == rowRef || env.lookupOption(ref.name).exists(isRowRef) + case _ => false + } + + private def isKeyField(ir: IR, keyFieldName: String): Boolean = ir match { + case GetField(struct, name) => fieldIsKeyField(struct, name, keyFieldName) + case Ref(name, _) => env.lookupOption(name).exists(isKeyField(_, keyFieldName)) + case _ => false + } + + private def fieldIsKeyField(struct: IR, fieldName: String, keyFieldName: String): Boolean = struct match { + case MakeStruct(fields) => fields.exists { case (n, f) => + n == fieldName && isKeyField(f, keyFieldName) + } + case SelectFields(o, fields) => fields.exists { f => + f == fieldName && fieldIsKeyField(o, fieldName, keyFieldName) + } + case _ => isRowRef(struct) && fieldName == keyFieldName + } + + def isFirstKey(ir: IR): Boolean = isKeyField(ir, rowKeyType.fieldNames.head) def isKeyStructPrefix(ir: IR): Boolean = ir match { - case MakeStruct(fields) => fields - .iterator - .map(_._2) - .zipWithIndex - .forall { case (fd, idx) => idx < rowKeyType.size && fd == GetField(rowRef, rowKeyType.fieldNames(idx)) } - case SelectFields(`rowRef`, fields) => keyFields.startsWith(fields) + case MakeStruct(fields) => + fields.size <= rowKeyType.size && fields.view.zipWithIndex.forall { case ((_, fd), idx) => + isKeyField(fd, rowKeyType.fieldNames(idx)) + } + case SelectFields(old, fields) => + fields.size <= rowKeyType.size && fields.view.zipWithIndex.forall { case (fd, idx) => + fieldIsKeyField(old, fd, rowKeyType.fieldNames(idx)) + } case _ => false } } @@ -267,10 +312,9 @@ object ExtractIntervalFilters { case _ => None } } - case Let(name, value, body) if name != es.rowRef.name => - // TODO: thread key identity through values, since this will break when CSE arrives - // TODO: thread predicates in `value` through `body` as a ref - extractAndRewrite(body, es) + case Let(name, value, body) => + // FIXME: ignores predicates in value + extractAndRewrite(body, es.bind(name, value)) .map { case (ir, intervals) => (Let(name, value, ir), intervals) } case _ => None } From 1575d760e0a13847722cfc6c4ceeffb4f68fab28 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 3 Aug 2023 16:11:28 -0400 Subject: [PATCH 066/180] [auth] Dont use the auth client for authz in the auth service (#13330) Came across this while doing #13307. The `AuthClient` decorators are used by services like Batch and CI to protect endpoints behind an authentication/authorization check. Those decorators might make a network request to the auth service to see who the user is and whether they're a developer. I realized that these decorators are also used to protect some endpoints on the auth service too, which albeit uniform felt silly to me (make a network request back to yourself instead of just making a function call). Creating new decorators to use within the auth service is a bit more code, but I personally think it's a much easier code path to follow. Only the last commit is this PR, as it's stacked. --- auth/auth/auth.py | 107 +++++++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index fb9774c9879..6a9e6c3933c 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -3,6 +3,7 @@ import logging import os import re +from functools import wraps from typing import List, Optional import aiohttp_session @@ -14,7 +15,6 @@ from prometheus_async.aio.web import server_stats # type: ignore from gear import ( - AuthClient, Database, K8sCache, Transaction, @@ -28,6 +28,7 @@ setup_aiohttp_session, transaction, ) +from gear.auth import AIOHTTPHandler, AuthenticatedAIOHTTPHandler, MaybeAuthenticatedAIOHTTPHandler from gear.cloud_config import get_global_config from gear.profiling import install_profiler_if_requested from hailtop import httpx @@ -65,7 +66,40 @@ routes = web.RouteTableDef() -auth = AuthClient() + +def authenticated_users_only(fun: AuthenticatedAIOHTTPHandler) -> AIOHTTPHandler: + @wraps(fun) + async def wrapped(request: web.Request) -> web.StreamResponse: + session_id = await get_session_id(request) + if not session_id: + raise web.HTTPUnauthorized() + userdata = await get_userinfo(request, session_id) + return await fun(request, userdata) + + return wrapped + + +def authenticated_devs_only(fun: AuthenticatedAIOHTTPHandler) -> AIOHTTPHandler: + @authenticated_users_only + @wraps(fun) + async def wrapped(request: web.Request, userdata: UserData) -> web.StreamResponse: + if userdata['is_developer'] != 1: + raise web.HTTPUnauthorized() + return await fun(request, userdata) + + return wrapped + + +def maybe_authenticated_user(fun: MaybeAuthenticatedAIOHTTPHandler) -> AIOHTTPHandler: + @wraps(fun) + async def wrapped(request: web.Request) -> web.StreamResponse: + session_id = await get_session_id(request) + if not session_id: + return await fun(request, None) + userdata = await get_userinfo(request, session_id) + return await fun(request, userdata) + + return wrapped async def user_from_login_id(db, login_id): @@ -186,13 +220,13 @@ async def get_healthcheck(_) -> web.Response: @routes.get('') @routes.get('/') -@auth.web_maybe_authenticated_user +@maybe_authenticated_user async def get_index(request: web.Request, userdata: Optional[UserData]) -> web.Response: return await render_template('auth', request, userdata, 'index.html', {}) @routes.get('/creating') -@auth.web_maybe_authenticated_user +@maybe_authenticated_user async def creating_account(request: web.Request, userdata: Optional[UserData]) -> web.Response: db = request.app['db'] session = await aiohttp_session.get_session(request) @@ -379,7 +413,7 @@ async def callback(request): @routes.post('/api/v1alpha/users/{user}/create') -@auth.rest_authenticated_developers_only +@authenticated_devs_only async def create_user(request: web.Request, _) -> web.Response: db: Database = request.app['db'] username = request.match_info['user'] @@ -419,7 +453,7 @@ async def create_user(request: web.Request, _) -> web.Response: @routes.get('/user') -@auth.web_authenticated_users_only() +@authenticated_users_only async def user_page(request: web.Request, userdata: UserData) -> web.Response: return await render_template('auth', request, userdata, 'user.html', {'cloud': CLOUD}) @@ -435,7 +469,7 @@ async def create_copy_paste_token(db, session_id, max_age_secs=300): @routes.post('/copy-paste-token') @check_csrf_token -@auth.web_authenticated_users_only() +@authenticated_users_only async def get_copy_paste_token(request: web.Request, userdata: UserData) -> web.Response: session = await aiohttp_session.get_session(request) session_id = session['session_id'] @@ -446,7 +480,7 @@ async def get_copy_paste_token(request: web.Request, userdata: UserData) -> web. @routes.post('/api/v1alpha/copy-paste-token') -@auth.rest_authenticated_users_only +@authenticated_users_only async def get_copy_paste_token_api(request: web.Request, userdata: UserData) -> web.Response: session_id = userdata['session_id'] db = request.app['db'] @@ -456,7 +490,7 @@ async def get_copy_paste_token_api(request: web.Request, userdata: UserData) -> @routes.post('/logout') @check_csrf_token -@auth.web_maybe_authenticated_user +@maybe_authenticated_user async def logout(request: web.Request, userdata: Optional[UserData]) -> web.HTTPFound: if not userdata: return web.HTTPFound(deploy_config.external_url('auth', '')) @@ -485,7 +519,7 @@ async def rest_login(request: web.Request) -> web.Response: @routes.get('/roles') -@auth.web_authenticated_developers_only() +@authenticated_devs_only async def get_roles(request: web.Request, userdata: UserData) -> web.Response: db = request.app['db'] roles = [x async for x in db.select_and_fetchall('SELECT * FROM roles;')] @@ -495,7 +529,7 @@ async def get_roles(request: web.Request, userdata: UserData) -> web.Response: @routes.post('/roles') @check_csrf_token -@auth.web_authenticated_developers_only() +@authenticated_devs_only async def post_create_role(request: web.Request, _) -> web.HTTPFound: session = await aiohttp_session.get_session(request) db = request.app['db'] @@ -516,7 +550,7 @@ async def post_create_role(request: web.Request, _) -> web.HTTPFound: @routes.get('/users') -@auth.web_authenticated_developers_only() +@authenticated_devs_only async def get_users(request: web.Request, userdata: UserData) -> web.Response: db = request.app['db'] users = [x async for x in db.select_and_fetchall('SELECT * FROM users;')] @@ -526,7 +560,7 @@ async def get_users(request: web.Request, userdata: UserData) -> web.Response: @routes.post('/users') @check_csrf_token -@auth.web_authenticated_developers_only() +@authenticated_devs_only async def post_create_user(request: web.Request, _) -> web.HTTPFound: session = await aiohttp_session.get_session(request) db = request.app['db'] @@ -551,7 +585,7 @@ async def post_create_user(request: web.Request, _) -> web.HTTPFound: @routes.get('/api/v1alpha/users') -@auth.rest_authenticated_developers_only +@authenticated_devs_only async def rest_get_users(request: web.Request, _) -> web.Response: db: Database = request.app['db'] _query = ''' @@ -563,7 +597,7 @@ async def rest_get_users(request: web.Request, _) -> web.Response: @routes.get('/api/v1alpha/users/{user}') -@auth.rest_authenticated_developers_only +@authenticated_devs_only async def rest_get_user(request: web.Request, _) -> web.Response: db: Database = request.app['db'] username = request.match_info['user'] @@ -603,7 +637,7 @@ async def _delete_user(db: Database, username: str, id: Optional[str]): @routes.post('/users/delete') @check_csrf_token -@auth.web_authenticated_developers_only() +@authenticated_devs_only async def delete_user(request: web.Request, _) -> web.HTTPFound: session = await aiohttp_session.get_session(request) db = request.app['db'] @@ -621,7 +655,7 @@ async def delete_user(request: web.Request, _) -> web.HTTPFound: @routes.delete('/api/v1alpha/users/{user}') -@auth.rest_authenticated_developers_only +@authenticated_devs_only async def rest_delete_user(request: web.Request, _) -> web.Response: db = request.app['db'] username = request.match_info['user'] @@ -699,7 +733,7 @@ async def maybe_pop_token(tx): @routes.post('/api/v1alpha/logout') -@auth.rest_authenticated_users_only +@authenticated_users_only async def rest_logout(request: web.Request, userdata: UserData) -> web.Response: session_id = userdata['session_id'] db = request.app['db'] @@ -735,21 +769,12 @@ async def get_userinfo(request: web.Request, session_id: str) -> UserData: @routes.get('/api/v1alpha/userinfo') -async def userinfo(request): - if 'Authorization' not in request.headers: - log.info('Authorization not in request.headers') - raise web.HTTPUnauthorized() - - auth_header = request.headers['Authorization'] - session_id = maybe_parse_bearer_header(auth_header) - if not session_id: - log.info('Bearer not in Authorization header') - raise web.HTTPUnauthorized() - - return json_response(await get_userinfo(request, session_id)) +@authenticated_users_only +async def userinfo(_, userdata: UserData) -> web.Response: + return json_response(userdata) -async def get_session_id(request): +async def get_session_id(request: web.Request) -> Optional[str]: if 'X-Hail-Internal-Authorization' in request.headers: return maybe_parse_bearer_header(request.headers['X-Hail-Internal-Authorization']) @@ -761,25 +786,17 @@ async def get_session_id(request): @routes.route('*', '/api/v1alpha/verify_dev_credentials') -async def verify_dev_credentials(request): - session_id = await get_session_id(request) - if not session_id: - raise web.HTTPUnauthorized() - userdata = await get_userinfo(request, session_id) - is_developer = userdata is not None and userdata['is_developer'] == 1 - if not is_developer: +@authenticated_users_only +async def verify_dev_credentials(_, userdata: UserData) -> web.Response: + if userdata['is_developer'] != 1: raise web.HTTPUnauthorized() return web.Response(status=200) @routes.route('*', '/api/v1alpha/verify_dev_or_sa_credentials') -async def verify_dev_or_sa_credentials(request): - session_id = await get_session_id(request) - if not session_id: - raise web.HTTPUnauthorized() - userdata = await get_userinfo(request, session_id) - is_developer_or_sa = userdata is not None and (userdata['is_developer'] == 1 or userdata['is_service_account'] == 1) - if not is_developer_or_sa: +@authenticated_users_only +async def verify_dev_or_sa_credentials(_, userdata: UserData) -> web.Response: + if userdata['is_developer'] != 1 or userdata['is_service_account'] != 1: raise web.HTTPUnauthorized() return web.Response(status=200) From 6733e040a707e0320d3301b0943073db0ccadd4d Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 3 Aug 2023 17:27:13 -0400 Subject: [PATCH 067/180] [batch] Fix transaction decorator to work with additional args (#13373) --- batch/batch/driver/main.py | 4 ++-- gear/gear/database.py | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 7d3d066a272..4bbae3e572e 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -1436,7 +1436,7 @@ async def compact(tx: Transaction, target: dict): targets = [target async for target in targets] for target in targets: - await compact(target) # pylint: disable=no-value-for-parameter + await compact(target) async def compact_agg_billing_project_users_by_date_table(app, db: Database): @@ -1508,7 +1508,7 @@ async def compact(tx: Transaction, target: dict): targets = [target async for target in targets] for target in targets: - await compact(target) # pylint: disable=no-value-for-parameter + await compact(target) async def scheduling_cancelling_bump(app): diff --git a/gear/gear/database.py b/gear/gear/database.py index a240eb6253e..487b31b275f 100644 --- a/gear/gear/database.py +++ b/gear/gear/database.py @@ -10,6 +10,7 @@ import kubernetes_asyncio.client import kubernetes_asyncio.config import pymysql +from typing_extensions import Concatenate, ParamSpec from gear.metrics import DB_CONNECTION_QUEUE_SIZE, SQL_TRANSACTIONS, PrometheusSQLTimer from hailtop.aiotools import BackgroundTaskManager @@ -61,15 +62,16 @@ async def wrapper(*args, **kwargs): T = TypeVar("T") +P = ParamSpec('P') def transaction(db: 'Database', read_only: bool = False): - def transformer(fun: Callable[['Transaction'], Awaitable[T]]) -> Callable[[], Awaitable[T]]: + def transformer(fun: Callable[Concatenate['Transaction', P], Awaitable[T]]) -> Callable[P, Awaitable[T]]: @functools.wraps(fun) @retry_transient_mysql_errors - async def wrapper(): + async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T: async with db.start(read_only=read_only) as tx: - return await fun(tx) + return await fun(tx, *args, **kwargs) return wrapper From 4ecc851b82e025653317dd0a3476e82e6ac3ca81 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 3 Aug 2023 21:18:43 -0400 Subject: [PATCH 068/180] [batch] Specify batch-driver as the default container in the batch-driver pod (#13374) `kubectl` commands like `exec` that deal with containers in pods will generally default to the first container in the pod. The `batch-driver` deployment has two containers, the envoy sidecar and the batch-driver python app. Since the `envoy` container is listed first, `kssh` and `sync.py` default to that container, but we basically always intend `batch-driver`. Instead of switching up the order, or adding a bunch of explicit container specification, this annotates `batch-driver` as the default container in the pod, so `kssh` and `sync.py` work with the batch driver. --- batch/deployment.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/batch/deployment.yaml b/batch/deployment.yaml index 558e06b8c19..b9322cab16d 100644 --- a/batch/deployment.yaml +++ b/batch/deployment.yaml @@ -106,6 +106,8 @@ spec: app: batch-driver hail.is/sha: "{{ code.sha }}" grafanak8sapp: "true" + annotations: + kubectl.kubernetes.io/default-container: batch-driver spec: serviceAccountName: batch {% if deploy %} From 5771a50c94ef0cd68125ed9ed9f68f2bfd7b76b6 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 3 Aug 2023 22:27:29 -0400 Subject: [PATCH 069/180] [devdocs] Add instructions on giving a dev admin access to their dev namespace (#13347) As part of the security POAMs, we'll follow up on this with instructions of making operator devs viewers + ability to assign themselves roles. This is just what I did for Sophie to give access just to the dev namespace. --- dev-docs/creating-a-developer-account.md | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/dev-docs/creating-a-developer-account.md b/dev-docs/creating-a-developer-account.md index ea9aa342426..e8df0258eac 100644 --- a/dev-docs/creating-a-developer-account.md +++ b/dev-docs/creating-a-developer-account.md @@ -31,3 +31,46 @@ Client IDs even though all they did was provide a very limited API: The `gcloud alpha iap oauth-clients list` command does not list our OAuth 2.0 Client ID. Presumably the type of client id that supports redirect URIs is special and completely unsupported by this API. + +# Google IAM and Kubernetes Roles + +In order to access the Kubernetes cluster, the extant developer should do the +following: + +- Navigate in the GCP Console to IAM and grant the IAM `Kubernetes Engine Cluster Viewer` role. + This will allow the new developer's google account to authenticate with the + cluster using `kubectl` but it will not grant the new developer access to k8s resources. +- To grant the new developer access to their developer namespace, the extant + developer should apply the following configuration through `kubectl apply`. + +```yaml +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: dev-admin + namespace: +rules: +- apiGroups: [""] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apps"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["*"] + verbs: ["*"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: -dev-admin-binding + namespace: +subjects: +- kind: User + name: + namespace: +roleRef: + kind: Role + name: dev-admin + apiGroup: "" +``` From 6608ab9010c271f4d43437bcc05285d9b2226129 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 4 Aug 2023 14:08:47 -0400 Subject: [PATCH 070/180] [auth] Fix verify_dev_or_sa_credentials (#13378) --- auth/auth/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index 6a9e6c3933c..3cdebf112a8 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -796,7 +796,7 @@ async def verify_dev_credentials(_, userdata: UserData) -> web.Response: @routes.route('*', '/api/v1alpha/verify_dev_or_sa_credentials') @authenticated_users_only async def verify_dev_or_sa_credentials(_, userdata: UserData) -> web.Response: - if userdata['is_developer'] != 1 or userdata['is_service_account'] != 1: + if userdata['is_developer'] != 1 and userdata['is_service_account'] != 1: raise web.HTTPUnauthorized() return web.Response(status=200) From 0a6f128ac058a6d4474122b8cbb294b7965423cd Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 4 Aug 2023 15:26:35 -0400 Subject: [PATCH 071/180] [qob] cancel the QoB test batch after a test is complete (#13326) --- hail/python/test/hail/conftest.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/hail/python/test/hail/conftest.py b/hail/python/test/hail/conftest.py index cded225403a..c7ee113ce48 100644 --- a/hail/python/test/hail/conftest.py +++ b/hail/python/test/hail/conftest.py @@ -1,15 +1,20 @@ +from typing import Dict import asyncio import hashlib import os +import logging import pytest -import pytest_timeout +from pytest import StashKey, CollectReport from hail import current_backend, init, reset_global_randomness from hail.backend.service_backend import ServiceBackend from .helpers import hl_init_for_test, hl_stop_for_test +log = logging.getLogger(__name__) + + def pytest_collection_modifyitems(config, items): n_splits = int(os.environ.get('HAIL_RUN_IMAGE_SPLITS', '1')) split_index = int(os.environ.get('HAIL_RUN_IMAGE_SPLIT_INDEX', '-1')) @@ -48,6 +53,17 @@ def reset_randomness(init_hail): reset_global_randomness() +test_results_key = StashKey[Dict[str, CollectReport]]() + + +@pytest.hookimpl(wrapper=True, tryfirst=True) +def pytest_runtest_makereport(item, call): + # from: https://docs.pytest.org/en/latest/example/simple.html#making-test-result-information-available-in-fixtures + report = yield + item.stash.setdefault(test_results_key, {})[report.when] = report + return report + + @pytest.fixture(autouse=True) def set_query_name(init_hail, request): backend = current_backend() @@ -55,6 +71,11 @@ def set_query_name(init_hail, request): backend.batch_attributes = dict(name=request.node.name) yield backend.batch_attributes = dict() - backend._batch = None + if backend._batch: + report: Dict[str, CollectReport] = request.node.stash[test_results_key] + if any(r.failed for r in report.values()): + log.info(f'cancelling failed test batch {backend._batch.id}') + asyncio.get_event_loop().run_until_complete(backend._batch.cancel()) + backend._batch = None else: yield From 7eb896402ef1c40cbe897e5e6f59f11edaaedf02 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 4 Aug 2023 17:27:53 -0400 Subject: [PATCH 072/180] [query] clarify the guarantees on hail.experimental and hail.vds (#13381) --- hail/python/hail/docs/experimental/index.rst | 6 ++++++ hail/python/hail/docs/vds/index.rst | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/hail/python/hail/docs/experimental/index.rst b/hail/python/hail/docs/experimental/index.rst index fb220c3266b..776b1836908 100644 --- a/hail/python/hail/docs/experimental/index.rst +++ b/hail/python/hail/docs/experimental/index.rst @@ -9,6 +9,12 @@ At present, the experimental module is organized into a few freestanding modules, linked immediately below, and many freestanding functions, documented on this page. +.. warning:: + + The functionality in this module may change or disappear entirely between different versions of + Hail. If you critically depend on functionality in this module, please create an issue to request + promotion of that functionality to non-experimental. Otherwise, that functionality may disappear! + .. toctree:: :maxdepth: 1 diff --git a/hail/python/hail/docs/vds/index.rst b/hail/python/hail/docs/vds/index.rst index 31b75dbbb5f..721fe420208 100644 --- a/hail/python/hail/docs/vds/index.rst +++ b/hail/python/hail/docs/vds/index.rst @@ -9,11 +9,6 @@ to combine, represent, and analyze 150,000 whole genomes. It has since been used large as 955,000 whole exomes. The :class:`.VariantDatasetCombiner` produces a :class:`.VariantDataset` by combining any number of GVCF and/or :class:`.VariantDataset` files. -.. warning:: - - The :class:`.VariantDataset` API is new and subject to change. While this is functionality tested - and used in production applications, it is still considered experimental. - .. warning:: Hail 0.1 also had a Variant Dataset class. Although pieces of the interfaces are similar, they should not From 973a1f8390d04d684179ed80e019e1347487d15a Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 4 Aug 2023 18:37:41 -0400 Subject: [PATCH 073/180] [security] bump cryptography again (#13375) --- ci/pinned-requirements.txt | 2 +- hail/python/hailtop/pinned-requirements.txt | 2 +- hail/python/pinned-requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/pinned-requirements.txt b/ci/pinned-requirements.txt index 25812040c48..34b7938ece0 100644 --- a/ci/pinned-requirements.txt +++ b/ci/pinned-requirements.txt @@ -27,7 +27,7 @@ click==8.1.6 # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt # zulip -cryptography==41.0.2 +cryptography==41.0.3 # via # -c hail/ci/../hail/python/pinned-requirements.txt # pyjwt diff --git a/hail/python/hailtop/pinned-requirements.txt b/hail/python/hailtop/pinned-requirements.txt index cb3525377c0..d0b261fe105 100644 --- a/hail/python/hailtop/pinned-requirements.txt +++ b/hail/python/hailtop/pinned-requirements.txt @@ -55,7 +55,7 @@ click==8.1.6 # via typer commonmark==0.9.1 # via rich -cryptography==41.0.2 +cryptography==41.0.3 # via # azure-identity # azure-storage-blob diff --git a/hail/python/pinned-requirements.txt b/hail/python/pinned-requirements.txt index 5062183ad4b..e432e69eb5c 100644 --- a/hail/python/pinned-requirements.txt +++ b/hail/python/pinned-requirements.txt @@ -96,7 +96,7 @@ commonmark==0.9.1 # rich contourpy==1.1.0 # via bokeh -cryptography==41.0.2 +cryptography==41.0.3 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-identity From e32182fb1e6430e8d297463a283a606354fc829a Mon Sep 17 00:00:00 2001 From: Edmund Higham Date: Fri, 4 Aug 2023 19:49:33 -0400 Subject: [PATCH 074/180] [query] Parameterise BlockMatrix tests in test_linalg.py (fixes #13261) (#13348) RR: https://github.com/hail-is/hail/issues/13261 Grouping asserts of distributed `BlockMatrix` queries via `BatchAssert` lead to repeated timeout failures during tests that used the batch-service backend. This change removes all `BatchAssert`s from `test_linalg.py`. It uses `pytest.mark.parameterize` to gain parallelism in test execution from the test driver. --- hail/python/test/hail/linalg/test_linalg.py | 2685 +++++++++---------- 1 file changed, 1305 insertions(+), 1380 deletions(-) diff --git a/hail/python/test/hail/linalg/test_linalg.py b/hail/python/test/hail/linalg/test_linalg.py index b9d83e856cd..cfecbc9382a 100644 --- a/hail/python/test/hail/linalg/test_linalg.py +++ b/hail/python/test/hail/linalg/test_linalg.py @@ -1,14 +1,14 @@ -import traceback - import pytest - +import math +import numpy as np import hail as hl + +from contextlib import contextmanager + +from hail.expr.expressions import ExpressionException from hail.linalg import BlockMatrix -from hail.utils import local_path_uri, FatalError, HailUserError +from hail.utils import FatalError, HailUserError from ..helpers import * -import numpy as np -import math -from hail.expr.expressions import ExpressionException def sparsify_numpy(np_mat, block_size, blocks_to_sparsify): @@ -36,1399 +36,1324 @@ def sparsify_numpy(np_mat, block_size, blocks_to_sparsify): return target_mat -class BatchedAsserts(): - - def __init__(self, batch_size=32): - self._batch_size = batch_size - - def __enter__(self): - self._a_list = [] - self._b_list = [] - self._comparison_funcs = [] - self._tbs = [] - return self - - def _assert_agree(self, a, b, f): - self._a_list.append(a) - self._b_list.append(b) - self._comparison_funcs.append(f) - self._tbs.append(traceback.format_stack()) - - def assert_eq(self, a, b): - self._assert_agree(a, b, np.testing.assert_equal) - - def assert_close(self, a, b): - self._assert_agree(a, b, np.testing.assert_allclose) - - def __exit__(self, *exc): - a_list = self._a_list - b_list = self._b_list - comparisons = self._comparison_funcs - tb = self._tbs - assert len(a_list) == len(b_list) - assert len(a_list) == len(comparisons) - assert len(a_list) == len(tb) - - all_bms = {} - - a_results = [] - for i, a in enumerate(a_list): - if isinstance(a, BlockMatrix): - all_bms[(0, i)] = a.to_ndarray() - a_results.append(None) - else: - a_results.append(np.array(a)) - - b_results = [] - for i, b in enumerate(b_list): - if isinstance(b, BlockMatrix): - all_bms[(1, i)] = b.to_ndarray() - b_results.append(None) - else: - b_results.append(np.array(b)) - - bm_keys = list(all_bms.keys()) - - vals = [] - batch_size = self._batch_size - n_bms = len(bm_keys) - for batch_start in range(0, n_bms, batch_size): - vals.extend(list(hl.eval(tuple([all_bms[k] for k in bm_keys[batch_start:batch_start + batch_size]])))) - - for (a_or_b, idx), v in zip(bm_keys, vals): - if a_or_b == 0: - a_results[idx] = v - else: - b_results[idx] = v - - for i, x in enumerate(a_results): - assert x is not None, i - for i, x in enumerate(b_results): - assert x is not None, i - - for a_res, b_res, comp_func, tb in zip(a_results, b_results, comparisons, tb): - try: - comp_func(a_res, b_res) - except AssertionError as e: - i = 0 - while i < len(tb): - if 'test/hail' in tb[i]: - break - i += 1 - raise AssertionError( - f'test failure:\n left={a_res}\n right={b_res}\n f={comp_func.__name__}\n failure at:\n{"".join(x for x in tb[i:])}') from e - - -def entry_expr_to_ndarray_vec(expr, mean_impute, center, normalize): - return np.squeeze(hl.eval(BlockMatrix.from_entry_expr( - expr, - mean_impute=mean_impute, - center=center, - normalize=normalize - ).to_ndarray())) - - -class Tests(unittest.TestCase): - @staticmethod - def _np_matrix(a): - if isinstance(a, BlockMatrix): - return hl.eval(a.to_ndarray()) - else: - return np.array(a) - - def _assert_eq(self, a, b): - anp = self._np_matrix(a) - bnp = self._np_matrix(b) - np.testing.assert_equal(anp, bnp) - - def _assert_close(self, a, b): - self.assertTrue(np.allclose(self._np_matrix(a), self._np_matrix(b))) - - def _assert_rectangles_eq(self, expected, rect_path, export_rects, binary=False): - for (i, r) in enumerate(export_rects): - piece_path = rect_path + '/rect-' + str(i) + '_' + '-'.join(map(str, r)) - with hl.current_backend().fs.open(piece_path, mode='rb' if binary else 'r') as file: - expected_rect = expected[r[0]:r[1], r[2]:r[3]] - if binary: - actual_rect = np.reshape( - np.frombuffer(file.read()), - (r[1] - r[0], r[3] - r[2])) - else: - actual_rect = np.loadtxt(file, ndmin=2) - self._assert_eq(expected_rect, actual_rect) - - def assert_sums_agree(self, bm, nd): - self.assertAlmostEqual(bm.sum(), np.sum(nd)) - self._assert_close(bm.sum(axis=0), np.sum(nd, axis=0, keepdims=True)) - self._assert_close(bm.sum(axis=1), np.sum(nd, axis=1, keepdims=True)) - - def test_from_entry_expr_empty_parts(self): - with hl.TemporaryDirectory(ensure_exists=False) as path: - mt = hl.balding_nichols_model(n_populations=5, n_variants=2000, n_samples=20, n_partitions=200) - mt = mt.filter_rows((mt.locus.position <= 500) | (mt.locus.position > 1500)).checkpoint(path) - bm = BlockMatrix.from_entry_expr(mt.GT.n_alt_alleles()) - nd = (bm @ bm.T).to_numpy() - assert nd.shape == (1000, 1000) - - @test_timeout(local=6 * 60, batch=6 * 60) - def test_from_entry_expr_options_1(self): - a = np.array([0.0, 1.0, 2.0]) - - mt = hl.utils.range_matrix_table(1, 3) - mt = mt.rename({'row_idx': 'v', 'col_idx': 's'}) - mt = mt.annotate_entries(x = hl.literal(a)[mt.s]) - - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, False, False, False), a) - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, False, True, False), a - 1.0) - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, False, False, True), a / np.sqrt(5)) - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, False, True, True), (a - 1.0) / np.sqrt(2)) - assert np.allclose(entry_expr_to_ndarray_vec(mt.x + 1 - 1, False, False, False), a) - - @test_timeout(local=6 * 60, batch=6 * 60) - def test_from_entry_expr_options_2(self): - mean_imputed = np.array([0.0, 1.0, 2.0]) - actual = hl.array([0.0, hl.missing(hl.tfloat), 2.0]) - - mt = hl.utils.range_matrix_table(1, 3) - mt = mt.rename({'row_idx': 'v', 'col_idx': 's'}) - mt = mt.annotate_entries(x = actual[mt.s]) - - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, True, False, False), mean_imputed) - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, True, True, False), mean_imputed - 1.0) - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, True, False, True), mean_imputed / np.sqrt(5)) - assert np.allclose(entry_expr_to_ndarray_vec(mt.x, True, True, True), (mean_imputed - 1.0) / np.sqrt(2)) - with self.assertRaises(Exception): - BlockMatrix.from_entry_expr(mt.x) - - def test_write_from_entry_expr_overwrite(self): - mt = hl.balding_nichols_model(1, 1, 1) - mt = mt.select_entries(x=mt.GT.n_alt_alleles()) - bm = BlockMatrix.from_entry_expr(mt.x) - - with hl.TemporaryDirectory(ensure_exists=False) as path: +def _np_matrix(a): + return hl.eval(a.to_ndarray()) \ + if isinstance(a, BlockMatrix) \ + else np.array(a) + + +def _assert_eq(a, b): + anp = _np_matrix(a) + bnp = _np_matrix(b) + np.testing.assert_equal(anp, bnp) + + +def _assert_close(a, b): + assert np.allclose(_np_matrix(a), _np_matrix(b)) + + +def _assert_rectangles_eq(expected, rect_path, export_rects, binary=False): + for (i, r) in enumerate(export_rects): + piece_path = rect_path + '/rect-' + str(i) + '_' + '-'.join(map(str, r)) + + with hl.current_backend().fs.open(piece_path, mode='rb' if binary else 'r') as file: + expected_rect = expected[r[0]:r[1], r[2]:r[3]] + actual_rect = np.loadtxt(file, ndmin=2) if not binary else np.reshape( + np.frombuffer(file.read()), + (r[1] - r[0], r[3] - r[2]) + ) + _assert_eq(expected_rect, actual_rect) + + +def assert_sums_agree(bm, nd): + assert bm.sum() == pytest.approx(np.sum(nd)) + _assert_close(bm.sum(axis=0), np.sum(nd, axis=0, keepdims=True)) + _assert_close(bm.sum(axis=1), np.sum(nd, axis=1, keepdims=True)) + + +def assert_np_arrays_eq(a, b): + assert np.array_equal(a, np.array(b)), f"a={a}, b={b}" + + +def test_from_entry_expr_empty_parts(): + with hl.TemporaryDirectory(ensure_exists=False) as path: + mt = hl.balding_nichols_model(n_populations=5, n_variants=2000, n_samples=20, n_partitions=200) + mt = mt.filter_rows((mt.locus.position <= 500) | (mt.locus.position > 1500)).checkpoint(path) + bm = BlockMatrix.from_entry_expr(mt.GT.n_alt_alleles()) + nd = (bm @ bm.T).to_numpy() + assert nd.shape == (1000, 1000) + + +@pytest.mark.parametrize( + 'mean_impute, center, normalize, mk_expected', + [ (False, False, False, lambda a: a, ) + , (False, False, True, lambda a: a / np.sqrt(5), ) + , (False, True, False, lambda a: a - 1.0, ) + , (False, True, True, lambda a: (a - 1.0) / np.sqrt(2)) + , (True, False, False, lambda a: a, ) + , (True, False, True, lambda a: a / np.sqrt(5), ) + , (True, True, False, lambda a: a - 1.0, ) + , (True, True, True, lambda a: (a - 1.0) / np.sqrt(2)) + ] +) +def test_from_entry_expr_options(mean_impute, center, normalize, mk_expected): + a = np.array([0.0, 1.0, 2.0]) + + mt = hl.utils.range_matrix_table(1, 3) + mt = mt.rename({'row_idx': 'v', 'col_idx': 's'}) + + xs = hl.array([0.0, hl.missing(hl.tfloat), 2.0]) if mean_impute else hl.literal(a) + mt = mt.annotate_entries(x = xs[mt.s]) + + expected = mk_expected(a) + + bm = BlockMatrix.from_entry_expr(mt.x, mean_impute, center, normalize) + actual = np.squeeze(hl.eval(bm.to_ndarray())) + assert np.allclose(actual, expected) + + +def test_from_entry_expr_raises_when_values_missing(): + mt = hl.utils.range_matrix_table(1, 3) + mt = mt.rename({'row_idx': 'v', 'col_idx': 's'}) + actual = hl.array([0.0, hl.missing(hl.tfloat), 2.0]) + mt = mt.annotate_entries(x = actual[mt.s]) + with pytest.raises(Exception, match='Cannot construct an ndarray with missing values'): + BlockMatrix.from_entry_expr(mt.x) + + +def test_write_from_entry_expr_overwrite(): + mt = hl.balding_nichols_model(1, 1, 1) + mt = mt.select_entries(x=mt.GT.n_alt_alleles()) + bm = BlockMatrix.from_entry_expr(mt.x) + + with hl.TemporaryDirectory(ensure_exists=False) as path: + BlockMatrix.write_from_entry_expr(mt.x, path) + with pytest.raises(FatalError): BlockMatrix.write_from_entry_expr(mt.x, path) - self.assertRaises(FatalError, lambda: BlockMatrix.write_from_entry_expr(mt.x, path)) - BlockMatrix.write_from_entry_expr(mt.x, path, overwrite=True) - self._assert_eq(BlockMatrix.read(path), bm) + BlockMatrix.write_from_entry_expr(mt.x, path, overwrite=True) + _assert_eq(BlockMatrix.read(path), bm) - with hl.TemporaryDirectory(ensure_exists=False) as path: - # non-field expressions currently take a separate code path + +# non-field expressions currently take a separate code path +def test_write_from_entry_expr_overwrite_non_field_expressions(): + mt = hl.balding_nichols_model(1, 1, 1) + mt = mt.select_entries(x=mt.GT.n_alt_alleles()) + bm = BlockMatrix.from_entry_expr(mt.x) + + with hl.TemporaryDirectory(ensure_exists=False) as path: + BlockMatrix.write_from_entry_expr(mt.x + 1, path) + with pytest.raises(FatalError): BlockMatrix.write_from_entry_expr(mt.x + 1, path) - self.assertRaises(FatalError, lambda: BlockMatrix.write_from_entry_expr(mt.x + 1, path)) - - BlockMatrix.write_from_entry_expr(mt.x + 2, path, overwrite=True) - self._assert_eq(BlockMatrix.read(path), bm + 2) - - def test_random_uniform(self): - uniform = BlockMatrix.random(10, 10, gaussian=False) - - nuniform = hl.eval(uniform.to_ndarray()) - for row in nuniform: - for entry in row: - assert entry > 0 - - def test_bm_to_numpy(self): - bm = BlockMatrix.from_ndarray(hl.nd.arange(20).map(lambda x: hl.float64(x)).reshape((4, 5))) - np_bm = bm.to_numpy() - self._assert_eq(np_bm, np.arange(20, dtype=np.float64).reshape((4, 5))) - - def test_numpy_round_trip_1(self): - n_rows = 10 - n_cols = 11 - data = np.random.rand(n_rows * n_cols) - - bm = BlockMatrix._create(n_rows, n_cols, data.tolist(), block_size=4) - a = data.reshape((n_rows, n_cols)) - - with hl.TemporaryFilename() as bm_f, hl.TemporaryFilename() as a_f: - bm.tofile(bm_f) - hl.current_backend().fs.open(a_f, mode='wb').write(a.tobytes()) - - a1 = bm.to_numpy() - a2 = BlockMatrix.from_numpy(a, block_size=5).to_numpy() - a3 = np.frombuffer( - hl.current_backend().fs.open(bm_f, mode='rb').read() - ).reshape((n_rows, n_cols)) - a4 = BlockMatrix.fromfile(a_f, n_rows, n_cols, block_size=3).to_numpy() - a5 = BlockMatrix.fromfile(bm_f, n_rows, n_cols).to_numpy() - - with BatchedAsserts() as b: - b.assert_eq(a1, a) - b.assert_eq(a2, a) - b.assert_eq(a3, a) - b.assert_eq(a4, a) - b.assert_eq(a5, a) - - def test_numpy_round_trip_2(self): - n_rows = 10 - n_cols = 11 - data = np.random.rand(n_rows * n_cols) - - bm = BlockMatrix._create(n_rows, n_cols, data.tolist(), block_size=4) - a = data.reshape((n_rows, n_cols)) - - bmt = bm.T - at = a.T - - with hl.TemporaryFilename() as bmt_f, hl.TemporaryFilename() as at_f: - bmt.tofile(bmt_f) - hl.current_backend().fs.open(at_f, mode='wb').write(at.tobytes()) - - at1 = bmt.to_numpy() - at2 = BlockMatrix.from_numpy(at).to_numpy() - at3 = np.frombuffer( - hl.current_backend().fs.open(bmt_f, mode='rb').read() - ).reshape((n_cols, n_rows)) - at4 = BlockMatrix.fromfile(at_f, n_cols, n_rows).to_numpy() - at5 = BlockMatrix.fromfile(bmt_f, n_cols, n_rows).to_numpy() - - with BatchedAsserts() as b: - b.assert_eq(at1, at) - b.assert_eq(at2, at) - b.assert_eq(at3, at) - b.assert_eq(at4, at) - b.assert_eq(at5, at) - - @fails_service_backend() - @fails_local_backend() - def test_numpy_round_trip_force_blocking(self): - n_rows = 10 - n_cols = 11 - data = np.random.rand(n_rows * n_cols) - a = data.reshape((n_rows, n_cols)) - - bm = BlockMatrix._create(n_rows, n_cols, data.tolist(), block_size=4) - self._assert_eq(bm.to_numpy(_force_blocking=True), a) - - @fails_service_backend() - @fails_local_backend() - def test_to_table(self): - schema = hl.tstruct(row_idx=hl.tint64, entries=hl.tarray(hl.tfloat64)) - rows = [{'row_idx': 0, 'entries': [0.0, 1.0]}, - {'row_idx': 1, 'entries': [2.0, 3.0]}, - {'row_idx': 2, 'entries': [4.0, 5.0]}, - {'row_idx': 3, 'entries': [6.0, 7.0]}, - {'row_idx': 4, 'entries': [8.0, 9.0]}] - - for n_partitions in [1, 2, 3]: - for block_size in [1, 2, 5]: - expected = hl.Table.parallelize(rows, schema, 'row_idx', n_partitions) - bm = BlockMatrix._create(5, 2, [float(i) for i in range(10)], block_size) - actual = bm.to_table_row_major(n_partitions) - self.assertTrue(expected._same(actual)) - - @fails_service_backend() - @fails_local_backend() - def test_to_table_maximum_cache_memory_in_bytes_limits(self): - bm = BlockMatrix._create(5, 2, [float(i) for i in range(10)], 2) - try: - bm.to_table_row_major(2, maximum_cache_memory_in_bytes=15)._force_count() - except Exception as exc: - assert 'BlockMatrixCachedPartFile must be able to hold at least one row of every block in memory' in exc.args[0] - else: - assert False - - bm = BlockMatrix._create(5, 2, [float(i) for i in range(10)], 2) - bm.to_table_row_major(2, maximum_cache_memory_in_bytes=16)._force_count() - - @fails_service_backend() - @fails_local_backend() - def test_to_matrix_table(self): - n_partitions = 2 - rows, cols = 2, 5 - bm = BlockMatrix._create(rows, cols, [float(i) for i in range(10)]) - actual = bm.to_matrix_table_row_major(n_partitions) - - expected = hl.utils.range_matrix_table(rows, cols) - expected = expected.annotate_entries(element=hl.float64(expected.row_idx * cols + expected.col_idx)) - expected = expected.key_cols_by(col_idx=hl.int64(expected.col_idx)) - expected = expected.key_rows_by(row_idx=hl.int64(expected.row_idx)) - assert expected._same(actual) - - bm = BlockMatrix.random(50, 100, block_size=25, seed=0) - mt = bm.to_matrix_table_row_major(n_partitions) - mt_round_trip = BlockMatrix.from_entry_expr(mt.element).to_matrix_table_row_major() - assert mt._same(mt_round_trip) - - @test_timeout(3 * 60, local=6 * 60) - def test_paired_elementwise_addition(self): - nx = np.array([[2.0]]) - nc = np.array([[1.0], [2.0]]) - nr = np.array([[1.0, 2.0, 3.0]]) - nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - - e = 2.0 - # BlockMatrixMap requires very simple IRs on the SparkBackend. If I use - # `from_ndarray` here, it generates an `NDArrayRef` expression that it can't handle. - # Will be fixed by improving FoldConstants handling of ndarrays or fully lowering BlockMatrix. - x = BlockMatrix._create(1, 1, [2.0], block_size=8) - c = BlockMatrix.from_ndarray(hl.literal(nc), block_size=8) - r = BlockMatrix.from_ndarray(hl.literal(nr), block_size=8) - m = BlockMatrix.from_ndarray(hl.literal(nm), block_size=8) - - self.assertRaises(TypeError, - lambda: x + np.array(['one'], dtype=str)) - - with BatchedAsserts() as b: - - b.assert_eq(+m, 0 + m) - b.assert_eq(-m, 0 - m) - - # addition - b.assert_eq(x + e, nx + e) - b.assert_eq(c + e, nc + e) - b.assert_eq(r + e, nr + e) - b.assert_eq(m + e, nm + e) - - b.assert_eq(x + e, e + x) - b.assert_eq(c + e, e + c) - b.assert_eq(r + e, e + r) - b.assert_eq(m + e, e + m) - - b.assert_eq(x + x, 2 * x) - b.assert_eq(c + c, 2 * c) - b.assert_eq(r + r, 2 * r) - b.assert_eq(m + m, 2 * m) - - b.assert_eq(x + c, np.array([[3.0], [4.0]])) - b.assert_eq(x + r, np.array([[3.0, 4.0, 5.0]])) - b.assert_eq(x + m, np.array([[3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])) - b.assert_eq(c + m, np.array([[2.0, 3.0, 4.0], [6.0, 7.0, 8.0]])) - b.assert_eq(r + m, np.array([[2.0, 4.0, 6.0], [5.0, 7.0, 9.0]])) - b.assert_eq(x + c, c + x) - b.assert_eq(x + r, r + x) - b.assert_eq(x + m, m + x) - b.assert_eq(c + m, m + c) - b.assert_eq(r + m, m + r) - - b.assert_eq(x + nx, x + x) - b.assert_eq(x + nc, x + c) - b.assert_eq(x + nr, x + r) - b.assert_eq(x + nm, x + m) - b.assert_eq(c + nx, c + x) - b.assert_eq(c + nc, c + c) - b.assert_eq(c + nm, c + m) - b.assert_eq(r + nx, r + x) - b.assert_eq(r + nr, r + r) - b.assert_eq(r + nm, r + m) - b.assert_eq(m + nx, m + x) - b.assert_eq(m + nc, m + c) - b.assert_eq(m + nr, m + r) - b.assert_eq(m + nm, m + m) - - @test_timeout(3 * 60, local=6 * 60) - def test_paired_elementwise_subtraction(self): - nx = np.array([[2.0]]) - nc = np.array([[1.0], [2.0]]) - nr = np.array([[1.0, 2.0, 3.0]]) - nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - - e = 2.0 - # BlockMatrixMap requires very simple IRs on the SparkBackend. If I use - # `from_ndarray` here, it generates an `NDArrayRef` expression that it can't handle. - # Will be fixed by improving FoldConstants handling of ndarrays or fully lowering BlockMatrix. - x = BlockMatrix._create(1, 1, [2.0], block_size=8) - c = BlockMatrix.from_ndarray(hl.literal(nc), block_size=8) - r = BlockMatrix.from_ndarray(hl.literal(nr), block_size=8) - m = BlockMatrix.from_ndarray(hl.literal(nm), block_size=8) - - with BatchedAsserts() as b: - b.assert_eq(x - e, nx - e) - b.assert_eq(c - e, nc - e) - b.assert_eq(r - e, nr - e) - b.assert_eq(m - e, nm - e) - - b.assert_eq(x - e, -(e - x)) - b.assert_eq(c - e, -(e - c)) - b.assert_eq(r - e, -(e - r)) - b.assert_eq(m - e, -(e - m)) - - b.assert_eq(x - x, np.zeros((1, 1))) - b.assert_eq(c - c, np.zeros((2, 1))) - b.assert_eq(r - r, np.zeros((1, 3))) - b.assert_eq(m - m, np.zeros((2, 3))) - - b.assert_eq(x - c, np.array([[1.0], [0.0]])) - b.assert_eq(x - r, np.array([[1.0, 0.0, -1.0]])) - b.assert_eq(x - m, np.array([[1.0, 0.0, -1.0], [-2.0, -3.0, -4.0]])) - b.assert_eq(c - m, np.array([[0.0, -1.0, -2.0], [-2.0, -3.0, -4.0]])) - b.assert_eq(r - m, np.array([[0.0, 0.0, 0.0], [-3.0, -3.0, -3.0]])) - b.assert_eq(x - c, -(c - x)) - b.assert_eq(x - r, -(r - x)) - b.assert_eq(x - m, -(m - x)) - b.assert_eq(c - m, -(m - c)) - b.assert_eq(r - m, -(m - r)) - - b.assert_eq(x - nx, x - x) - b.assert_eq(x - nc, x - c) - b.assert_eq(x - nr, x - r) - b.assert_eq(x - nm, x - m) - b.assert_eq(c - nx, c - x) - b.assert_eq(c - nc, c - c) - b.assert_eq(c - nm, c - m) - b.assert_eq(r - nx, r - x) - b.assert_eq(r - nr, r - r) - b.assert_eq(r - nm, r - m) - b.assert_eq(m - nx, m - x) - b.assert_eq(m - nc, m - c) - b.assert_eq(m - nr, m - r) - b.assert_eq(m - nm, m - m) - - @test_timeout(3 * 60, local=6 * 60) - def test_paired_elementwise_multiplication(self): - nx = np.array([[2.0]]) - nc = np.array([[1.0], [2.0]]) - nr = np.array([[1.0, 2.0, 3.0]]) - nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - - e = 2.0 - # BlockMatrixMap requires very simple IRs on the SparkBackend. If I use - # `from_ndarray` here, it generates an `NDArrayRef` expression that it can't handle. - # Will be fixed by improving FoldConstants handling of ndarrays or fully lowering BlockMatrix. - x = BlockMatrix._create(1, 1, [2.0], block_size=8) - c = BlockMatrix.from_ndarray(hl.literal(nc), block_size=8) - r = BlockMatrix.from_ndarray(hl.literal(nr), block_size=8) - m = BlockMatrix.from_ndarray(hl.literal(nm), block_size=8) - - with BatchedAsserts() as b: - b.assert_eq(x * e, nx * e) - b.assert_eq(c * e, nc * e) - b.assert_eq(r * e, nr * e) - b.assert_eq(m * e, nm * e) - - b.assert_eq(x * e, e * x) - b.assert_eq(c * e, e * c) - b.assert_eq(r * e, e * r) - b.assert_eq(m * e, e * m) - - b.assert_eq(x * x, x ** 2) - b.assert_eq(c * c, c ** 2) - b.assert_eq(r * r, r ** 2) - b.assert_eq(m * m, m ** 2) - - b.assert_eq(x * c, np.array([[2.0], [4.0]])) - b.assert_eq(x * r, np.array([[2.0, 4.0, 6.0]])) - b.assert_eq(x * m, np.array([[2.0, 4.0, 6.0], [8.0, 10.0, 12.0]])) - b.assert_eq(c * m, np.array([[1.0, 2.0, 3.0], [8.0, 10.0, 12.0]])) - b.assert_eq(r * m, np.array([[1.0, 4.0, 9.0], [4.0, 10.0, 18.0]])) - b.assert_eq(x * c, c * x) - b.assert_eq(x * r, r * x) - b.assert_eq(x * m, m * x) - b.assert_eq(c * m, m * c) - b.assert_eq(r * m, m * r) - - b.assert_eq(x * nx, x * x) - b.assert_eq(x * nc, x * c) - b.assert_eq(x * nr, x * r) - b.assert_eq(x * nm, x * m) - b.assert_eq(c * nx, c * x) - b.assert_eq(c * nc, c * c) - b.assert_eq(c * nm, c * m) - b.assert_eq(r * nx, r * x) - b.assert_eq(r * nr, r * r) - b.assert_eq(r * nm, r * m) - b.assert_eq(m * nx, m * x) - b.assert_eq(m * nc, m * c) - b.assert_eq(m * nr, m * r) - b.assert_eq(m * nm, m * m) - - @test_timeout(3 * 60, local=6 * 60) - def test_paired_elementwise_division(self): - nx = np.array([[2.0]]) - nc = np.array([[1.0], [2.0]]) - nr = np.array([[1.0, 2.0, 3.0]]) - nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - - e = 2.0 + + BlockMatrix.write_from_entry_expr(mt.x + 2, path, overwrite=True) + _assert_eq(BlockMatrix.read(path), bm + 2) + + +def test_random_uniform(): + uniform = BlockMatrix.random(10, 10, gaussian=False) + + nuniform = hl.eval(uniform.to_ndarray()) + for row in nuniform: + for entry in row: + assert entry > 0 + + +def test_bm_to_numpy(): + bm = BlockMatrix.from_ndarray(hl.nd.arange(20).map(hl.float64).reshape((4, 5))) + np_bm = bm.to_numpy() + _assert_eq(np_bm, np.arange(20, dtype=np.float64).reshape((4, 5))) + + +def test_bm_transpose_to_numpy(): + bm = BlockMatrix.from_ndarray(hl.nd.arange(20).map(hl.float64).reshape((4, 5))) + np_bm = bm.T.to_numpy() + _assert_eq(np_bm, np.arange(20, dtype=np.float64).reshape((4, 5)).T) + + +@contextmanager +def block_matrix_to_tmp_file(data: 'np.ndarray', transpose=False) -> 'str': + with hl.TemporaryFilename() as f: + (n_rows, n_cols) = data.shape + bm = BlockMatrix._create(n_rows, n_cols, data.flatten().tolist(), block_size=4) + + if transpose: + bm = bm.T + + bm.tofile(f) + yield f + + +def test_block_matrix_from_numpy(): + data = np.random.rand(10, 11) + bm = BlockMatrix.from_numpy(data, block_size=5) + _assert_eq(data, bm.to_numpy()) + + +def test_block_matrix_from_numpy_transpose(): + data = np.random.rand(10, 11) + bm = BlockMatrix.from_numpy(data.T, block_size=5) + _assert_eq(data, bm.T.to_numpy()) + + +def test_block_matrix_to_file_transpose(): + data = np.random.rand(10, 11) + with block_matrix_to_tmp_file(data, transpose=True) as f: + _assert_eq(data.T, np + .frombuffer(hl.current_backend().fs.open(f, mode='rb').read()) + .reshape((11, 10)) + ) + + +def test_numpy_read_block_matrix_to_file(): + data = np.random.rand(10, 11) + with block_matrix_to_tmp_file(data) as f: + _assert_eq(data, np + .frombuffer(hl.current_backend().fs.open(f, mode='rb').read()) + .reshape((10, 11)) + ) + + +def test_block_matrix_from_numpy_bytes(): + data = np.random.rand(10, 11) + with hl.TemporaryFilename() as f: + hl.current_backend().fs.open(f, mode='wb').write(data.tobytes()) + array = BlockMatrix.fromfile(f, 10, 11, block_size=3).to_numpy() + _assert_eq(array, data) + + +def test_block_matrix_from_file(): + data = np.random.rand(10, 11) + with block_matrix_to_tmp_file(data) as f: + array = BlockMatrix.fromfile(f, 10, 11).to_numpy() + _assert_eq(array, data) + + +@fails_service_backend() +@fails_local_backend() +def test_numpy_round_trip_force_blocking(): + n_rows = 10 + n_cols = 11 + data = np.random.rand(n_rows * n_cols) + a = data.reshape((n_rows, n_cols)) + + bm = BlockMatrix._create(n_rows, n_cols, data.tolist(), block_size=4) + _assert_eq(bm.to_numpy(_force_blocking=True), a) + + +@fails_service_backend() +@fails_local_backend() +@pytest.mark.parametrize( + 'n_partitions,block_size', + [ (n_partitions, block_size) + for n_partitions in [1, 2, 3] + for block_size in [1, 2, 5] + ] +) +def test_to_table(n_partitions, block_size): + schema = hl.tstruct(row_idx=hl.tint64, entries=hl.tarray(hl.tfloat64)) + rows = [{'row_idx': 0, 'entries': [0.0, 1.0]}, + {'row_idx': 1, 'entries': [2.0, 3.0]}, + {'row_idx': 2, 'entries': [4.0, 5.0]}, + {'row_idx': 3, 'entries': [6.0, 7.0]}, + {'row_idx': 4, 'entries': [8.0, 9.0]}] + + expected = hl.Table.parallelize(rows, schema, 'row_idx', n_partitions) + bm = BlockMatrix._create(5, 2, [float(i) for i in range(10)], block_size) + actual = bm.to_table_row_major(n_partitions) + assert expected._same(actual) + + +@fails_service_backend() +@fails_local_backend() +def test_to_table_maximum_cache_memory_in_bytes_limits(): + bm = BlockMatrix._create(5, 2, [float(i) for i in range(10)], 2) + + with pytest.raises(Exception) as exc_info: + bm.to_table_row_major(2, maximum_cache_memory_in_bytes=15)._force_count() + + assert 'BlockMatrixCachedPartFile must be able to hold at least one row of every block in memory' in exc_info.value.args[0] + + bm = BlockMatrix._create(5, 2, [float(i) for i in range(10)], 2) + bm.to_table_row_major(2, maximum_cache_memory_in_bytes=16)._force_count() + + +@fails_service_backend() +@fails_local_backend() +def test_to_matrix_table_0(): + n_partitions = 2 + rows, cols = 2, 5 + bm = BlockMatrix._create(rows, cols, [float(i) for i in range(10)]) + actual = bm.to_matrix_table_row_major(n_partitions) + + expected = hl.utils.range_matrix_table(rows, cols) + expected = expected.annotate_entries(element=hl.float64(expected.row_idx * cols + expected.col_idx)) + expected = expected.key_cols_by(col_idx=hl.int64(expected.col_idx)) + expected = expected.key_rows_by(row_idx=hl.int64(expected.row_idx)) + assert expected._same(actual) + + +@fails_service_backend() +@fails_local_backend() +def test_to_matrix_table_1(): + n_partitions = 2 + bm = BlockMatrix.random(50, 100, block_size=25, seed=0) + mt = bm.to_matrix_table_row_major(n_partitions) + mt_round_trip = BlockMatrix.from_entry_expr(mt.element).to_matrix_table_row_major() + assert mt._same(mt_round_trip) + + +@pytest.fixture(scope='module') +def block_matrix_bindings(): + nc = np.array([[1.0], [2.0]]) + nr = np.array([[1.0, 2.0, 3.0]]) + nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) + nrow = np.array([[7.0, 8.0, 9.0]]) + nsquare = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]) + + + yield { + 'nx': np.array([[2.0]]), + 'nc': nc, + 'nr': nr, + 'nm': nm, + 'nrow': nrow, + 'nsquare': nsquare, + + 'e': 2.0, + # BlockMatrixMap requires very simple IRs on the SparkBackend. If I use # `from_ndarray` here, it generates an `NDArrayRef` expression that it can't handle. # Will be fixed by improving FoldConstants handling of ndarrays or fully lowering BlockMatrix. - x = BlockMatrix._create(1, 1, [2.0], block_size=8) - c = BlockMatrix.from_ndarray(hl.literal(nc), block_size=8) - r = BlockMatrix.from_ndarray(hl.literal(nr), block_size=8) - m = BlockMatrix.from_ndarray(hl.literal(nm), block_size=8) - - with BatchedAsserts() as b: - b.assert_close(x / e, nx / e) - b.assert_close(c / e, nc / e) - b.assert_close(r / e, nr / e) - b.assert_close(m / e, nm / e) - - b.assert_close(x / e, 1 / (e / x)) - b.assert_close(c / e, 1 / (e / c)) - b.assert_close(r / e, 1 / (e / r)) - b.assert_close(m / e, 1 / (e / m)) - - b.assert_close(x / x, np.ones((1, 1))) - b.assert_close(c / c, np.ones((2, 1))) - b.assert_close(r / r, np.ones((1, 3))) - b.assert_close(m / m, np.ones((2, 3))) - - b.assert_close(x / c, np.array([[2 / 1.0], [2 / 2.0]])) - b.assert_close(x / r, np.array([[2 / 1.0, 2 / 2.0, 2 / 3.0]])) - b.assert_close(x / m, np.array([[2 / 1.0, 2 / 2.0, 2 / 3.0], [2 / 4.0, 2 / 5.0, 2 / 6.0]])) - b.assert_close(c / m, np.array([[1 / 1.0, 1 / 2.0, 1 / 3.0], [2 / 4.0, 2 / 5.0, 2 / 6.0]])) - b.assert_close(r / m, np.array([[1 / 1.0, 2 / 2.0, 3 / 3.0], [1 / 4.0, 2 / 5.0, 3 / 6.0]])) - b.assert_close(x / c, 1 / (c / x)) - b.assert_close(x / r, 1 / (r / x)) - b.assert_close(x / m, 1 / (m / x)) - b.assert_close(c / m, 1 / (m / c)) - b.assert_close(r / m, 1 / (m / r)) - - b.assert_close(x / nx, x / x) - b.assert_close(x / nc, x / c) - b.assert_close(x / nr, x / r) - b.assert_close(x / nm, x / m) - b.assert_close(c / nx, c / x) - b.assert_close(c / nc, c / c) - b.assert_close(c / nm, c / m) - b.assert_close(r / nx, r / x) - b.assert_close(r / nr, r / r) - b.assert_close(r / nm, r / m) - b.assert_close(m / nx, m / x) - b.assert_close(m / nc, m / c) - b.assert_close(m / nr, m / r) - b.assert_close(m / nm, m / m) - - - def test_special_elementwise_ops(self): - nm = np.array([[1.0, 2.0, 3.0, 3.14], [4.0, 5.0, 6.0, 12.12]]) - m = BlockMatrix.from_ndarray(hl.nd.array(nm)) - - self._assert_close(m ** 3, nm ** 3) - self._assert_close(m.sqrt(), np.sqrt(nm)) - self._assert_close(m.ceil(), np.ceil(nm)) - self._assert_close(m.floor(), np.floor(nm)) - self._assert_close(m.log(), np.log(nm)) - self._assert_close((m - 4).abs(), np.abs(nm - 4)) - - def test_matrix_ops(self): - nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - m = BlockMatrix.from_ndarray(hl.nd.array(nm), block_size=2) - nsquare = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]) - square = BlockMatrix.from_ndarray(hl.nd.array(nsquare), block_size=2) - - nrow = np.array([[7.0, 8.0, 9.0]]) - row = BlockMatrix.from_ndarray(hl.nd.array(nrow), block_size=2) - - with BatchedAsserts() as b: - b.assert_eq(m.T, nm.T) - b.assert_eq(m.T, nm.T) - b.assert_eq(row.T, nrow.T) - - b.assert_eq(m @ m.T, nm @ nm.T) - b.assert_eq(m @ nm.T, nm @ nm.T) - b.assert_eq(row @ row.T, nrow @ nrow.T) - b.assert_eq(row @ nrow.T, nrow @ nrow.T) - - b.assert_eq(m.T @ m, nm.T @ nm) - b.assert_eq(m.T @ nm, nm.T @ nm) - b.assert_eq(row.T @ row, nrow.T @ nrow) - b.assert_eq(row.T @ nrow, nrow.T @ nrow) - - self.assertRaises(ValueError, lambda: m @ m) - self.assertRaises(ValueError, lambda: m @ nm) - - b.assert_eq(m.diagonal(), np.array([[1.0, 5.0]])) - b.assert_eq(m.T.diagonal(), np.array([[1.0, 5.0]])) - b.assert_eq((m @ m.T).diagonal(), np.array([[14.0, 77.0]])) - - def test_matrix_sums(self): - nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - m = BlockMatrix.from_ndarray(hl.nd.array(nm), block_size=2) - nsquare = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]) - square = BlockMatrix.from_ndarray(hl.nd.array(nsquare), block_size=2) - - nrow = np.array([[7.0, 8.0, 9.0]]) - row = BlockMatrix.from_ndarray(hl.nd.array(nrow), block_size=2) - - with BatchedAsserts() as b: - - b.assert_eq(m.sum(axis=0).T, np.array([[5.0], [7.0], [9.0]])) - b.assert_eq(m.sum(axis=1).T, np.array([[6.0, 15.0]])) - b.assert_eq(m.sum(axis=0).T + row, np.array([[12.0, 13.0, 14.0], - [14.0, 15.0, 16.0], - [16.0, 17.0, 18.0]])) - b.assert_eq(m.sum(axis=0) + row.T, np.array([[12.0, 14.0, 16.0], - [13.0, 15.0, 17.0], - [14.0, 16.0, 18.0]])) - b.assert_eq(square.sum(axis=0).T + square.sum(axis=1), np.array([[18.0], [30.0], [42.0]])) - - @fails_service_backend() - @fails_local_backend() - def test_tree_matmul(self): - nm = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - m = BlockMatrix.from_numpy(nm, block_size=2) - nrow = np.array([[7.0, 8.0, 9.0]]) - row = BlockMatrix.from_numpy(nrow, block_size=2) - - with BatchedAsserts() as b: - - b.assert_eq(m.tree_matmul(m.T, splits=2), nm @ nm.T) - b.assert_eq(m.tree_matmul(nm.T, splits=2), nm @ nm.T) - b.assert_eq(row.tree_matmul(row.T, splits=2), nrow @ nrow.T) - b.assert_eq(row.tree_matmul(nrow.T, splits=2), nrow @ nrow.T) - - b.assert_eq(m.T.tree_matmul(m, splits=2), nm.T @ nm) - b.assert_eq(m.T.tree_matmul(nm, splits=2), nm.T @ nm) - b.assert_eq(row.T.tree_matmul(row, splits=2), nrow.T @ nrow) - b.assert_eq(row.T.tree_matmul(nrow, splits=2), nrow.T @ nrow) - - # Variety of block sizes and splits - fifty_by_sixty = np.arange(50 * 60).reshape((50, 60)) - sixty_by_twenty_five = np.arange(60 * 25).reshape((60, 25)) - block_sizes = [7, 10] - split_sizes = [2, 9] - for block_size in block_sizes: - bm_fifty_by_sixty = BlockMatrix.from_numpy(fifty_by_sixty, block_size) - bm_sixty_by_twenty_five = BlockMatrix.from_numpy(sixty_by_twenty_five, block_size) - for split_size in split_sizes: - b.assert_eq(bm_fifty_by_sixty.tree_matmul(bm_fifty_by_sixty.T, splits=split_size), fifty_by_sixty @ fifty_by_sixty.T) - b.assert_eq(bm_fifty_by_sixty.tree_matmul(bm_sixty_by_twenty_five, splits=split_size), fifty_by_sixty @ sixty_by_twenty_five) - - def test_fill(self): - nd = np.ones((3, 5)) - bm = BlockMatrix.fill(3, 5, 1.0) - bm2 = BlockMatrix.fill(3, 5, 1.0, block_size=2) - - with BatchedAsserts() as b: - - self.assertTrue(bm.block_size == BlockMatrix.default_block_size()) - self.assertTrue(bm2.block_size == 2) - b.assert_eq(bm, nd) - b.assert_eq(bm2, nd) - - def test_sum(self): - nd = np.arange(11 * 13, dtype=np.float64).reshape((11, 13)) - bm = BlockMatrix.from_ndarray(hl.literal(nd), block_size=3) - - self.assert_sums_agree(bm, nd) - - @fails_local_backend - @fails_service_backend(reason='ExecuteContext.scoped requires SparkBackend') - def test_sum_with_sparsify(self): - nd = np.zeros(shape=(5, 7)) - nd[2, 4] = 1.0 - nd[2, 5] = 2.0 - nd[3, 4] = 3.0 - nd[3, 5] = 4.0 - - hnd = hl.nd.array(nd) - bm = BlockMatrix.from_ndarray(hnd, block_size=2).sparsify_rectangles([[2, 4, 4, 6]]) - - bm2 = BlockMatrix.from_ndarray(hnd, block_size=2).sparsify_rectangles([[2, 4, 4, 6], [0, 5, 0, 1]]) - - bm3 = BlockMatrix.from_ndarray(hnd, block_size=2).sparsify_rectangles([[2, 4, 4, 6], [0, 1, 0, 7]]) - - nd4 = np.zeros(shape=(5, 7)) - bm4 = BlockMatrix.fill(5, 7, value=0.0, block_size=2).sparsify_rectangles([]) - - self.assert_sums_agree(bm, nd) - self.assert_sums_agree(bm2, nd) - self.assert_sums_agree(bm3, nd) - self.assert_sums_agree(bm4, nd4) - - def test_slicing(self): - nd = np.array(np.arange(0, 80, dtype=float)).reshape(8, 10) - bm = BlockMatrix.from_ndarray(hl.literal(nd), block_size=3) - - for indices in [(0, 0), (5, 7), (-3, 9), (-8, -10)]: - self._assert_eq(bm[indices], nd[indices]) - - with BatchedAsserts() as b: - - for indices in [(0, slice(3, 4)), - (1, slice(3, 4)), - (-8, slice(3, 4)), - (-1, slice(3, 4))]: - b.assert_eq(bm[indices], np.expand_dims(nd[indices], 0)) - b.assert_eq(bm[indices] - bm, nd[indices] - nd) - b.assert_eq(bm - bm[indices], nd - nd[indices]) - - for indices in [(slice(3, 4), 0), - (slice(3, 4), 1), - (slice(3, 4), -8), - (slice(3, 4), -1)]: - b.assert_eq(bm[indices], np.expand_dims(nd[indices], 1)) - b.assert_eq(bm[indices] - bm, nd[indices] - nd) - b.assert_eq(bm - bm[indices], nd - nd[indices]) - - for indices in [ - (slice(0, 8), slice(0, 10)), - (slice(0, 8, 2), slice(0, 10, 2)), - (slice(2, 4), slice(5, 7)), - (slice(-8, -1), slice(-10, -1)), - (slice(-8, -1, 2), slice(-10, -1, 2)), - (slice(None, 4, 1), slice(None, 4, 1)), - (slice(4, None), slice(4, None)), - (slice(None, None), slice(None, None)) - ]: - b.assert_eq(bm[indices], nd[indices]) - b.assert_eq(bm[indices][:, :2], nd[indices][:, :2]) - b.assert_eq(bm[indices][:2, :], nd[indices][:2, :]) - - self.assertRaises(ValueError, lambda: bm[0, ]) - - self.assertRaises(ValueError, lambda: bm[9, 0]) - self.assertRaises(ValueError, lambda: bm[-9, 0]) - self.assertRaises(ValueError, lambda: bm[0, 11]) - self.assertRaises(ValueError, lambda: bm[0, -11]) - - self.assertRaises(ValueError, lambda: bm[::-1, 0]) - self.assertRaises(ValueError, lambda: bm[0, ::-1]) - - self.assertRaises(ValueError, lambda: bm[:0, 0]) - self.assertRaises(ValueError, lambda: bm[0, :0]) - - self.assertRaises(ValueError, lambda: bm[0:9, 0]) - self.assertRaises(ValueError, lambda: bm[-9:, 0]) - self.assertRaises(ValueError, lambda: bm[:-9, 0]) - - self.assertRaises(ValueError, lambda: bm[0, :11]) - self.assertRaises(ValueError, lambda: bm[0, -11:]) - self.assertRaises(ValueError, lambda: bm[0, :-11]) - - def test_diagonal_sparse(self): - nd = np.array([[ 1.0, 2.0, 3.0, 4.0], - [ 5.0, 6.0, 7.0, 8.0], - [ 9.0, 10.0, 11.0, 12.0], - [13.0, 14.0, 15.0, 16.0], - [17.0, 18.0, 19.0, 20.0]]) + 'x': BlockMatrix._create(1, 1, [2.0], block_size=8), + 'c': BlockMatrix.from_ndarray(hl.literal(nc), block_size=8), + 'r': BlockMatrix.from_ndarray(hl.literal(nr), block_size=8), + 'm': BlockMatrix.from_ndarray(hl.literal(nm), block_size=8), + 'row': BlockMatrix.from_ndarray(hl.nd.array(nrow), block_size=8), + 'square': BlockMatrix.from_ndarray(hl.nd.array(nsquare), block_size=8) + } + +@pytest.mark.parametrize( + 'x, y', + [ # addition + ('+m', '0 + m') + , ('x + e', 'nx + e') + , ('c + e', 'nc + e') + , ('r + e', 'nr + e') + , ('m + e', 'nm + e') + , ('x + e', 'e + x') + , ('c + e', 'e + c') + , ('r + e', 'e + r') + , ('m + e', 'e + m') + , ('x + x', '2 * x') + , ('c + c', '2 * c') + , ('r + r', '2 * r') + , ('m + m', '2 * m') + , ('x + c', 'np.array([[3.0], [4.0]])') + , ('x + r', 'np.array([[3.0, 4.0, 5.0]])') + , ('x + m', 'np.array([[3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])') + , ('c + m', 'np.array([[2.0, 3.0, 4.0], [6.0, 7.0, 8.0]])') + , ('r + m', 'np.array([[2.0, 4.0, 6.0], [5.0, 7.0, 9.0]])') + , ('x + c', 'c + x') + , ('x + r', 'r + x') + , ('x + m', 'm + x') + , ('c + m', 'm + c') + , ('r + m', 'm + r') + , ('x + nx', 'x + x') + , ('x + nc', 'x + c') + , ('x + nr', 'x + r') + , ('x + nm', 'x + m') + , ('c + nx', 'c + x') + , ('c + nc', 'c + c') + , ('c + nm', 'c + m') + , ('r + nx', 'r + x') + , ('r + nr', 'r + r') + , ('r + nm', 'r + m') + , ('m + nx', 'm + x') + , ('m + nc', 'm + c') + , ('m + nr', 'm + r') + , ('m + nm', 'm + m') + + # subtraction + , ('-m', '0 - m') + , ('x - e', 'nx - e') + , ('c - e', 'nc - e') + , ('r - e', 'nr - e') + , ('m - e', 'nm - e') + , ('x - e', '-(e - x)') + , ('c - e', '-(e - c)') + , ('r - e', '-(e - r)') + , ('m - e', '-(e - m)') + , ('x - x', 'np.zeros((1, 1))') + , ('c - c', 'np.zeros((2, 1))') + , ('r - r', 'np.zeros((1, 3))') + , ('m - m', 'np.zeros((2, 3))') + , ('x - c', 'np.array([[1.0], [0.0]])') + , ('x - r', 'np.array([[1.0, 0.0, -1.0]])') + , ('x - m', 'np.array([[1.0, 0.0, -1.0], [-2.0, -3.0, -4.0]])') + , ('c - m', 'np.array([[0.0, -1.0, -2.0], [-2.0, -3.0, -4.0]])') + , ('r - m', 'np.array([[0.0, 0.0, 0.0], [-3.0, -3.0, -3.0]])') + , ('x - c', '-(c - x)') + , ('x - r', '-(r - x)') + , ('x - m', '-(m - x)') + , ('c - m', '-(m - c)') + , ('r - m', '-(m - r)') + , ('x - nx', 'x - x') + , ('x - nc', 'x - c') + , ('x - nr', 'x - r') + , ('x - nm', 'x - m') + , ('c - nx', 'c - x') + , ('c - nc', 'c - c') + , ('c - nm', 'c - m') + , ('r - nx', 'r - x') + , ('r - nr', 'r - r') + , ('r - nm', 'r - m') + , ('m - nx', 'm - x') + , ('m - nc', 'm - c') + , ('m - nr', 'm - r') + , ('m - nm', 'm - m') + + # multiplication + , ('x * e', 'nx * e') + , ('c * e', 'nc * e') + , ('r * e', 'nr * e') + , ('m * e', 'nm * e') + , ('x * e', 'e * x') + , ('c * e', 'e * c') + , ('r * e', 'e * r') + , ('m * e', 'e * m') + , ('x * x', 'x ** 2') + , ('c * c', 'c ** 2') + , ('r * r', 'r ** 2') + , ('m * m', 'm ** 2') + , ('x * c', 'np.array([[2.0], [4.0]])') + , ('x * r', 'np.array([[2.0, 4.0, 6.0]])') + , ('x * m', 'np.array([[2.0, 4.0, 6.0], [8.0, 10.0, 12.0]])') + , ('c * m', 'np.array([[1.0, 2.0, 3.0], [8.0, 10.0, 12.0]])') + , ('r * m', 'np.array([[1.0, 4.0, 9.0], [4.0, 10.0, 18.0]])') + , ('x * c', 'c * x') + , ('x * r', 'r * x') + , ('x * m', 'm * x') + , ('c * m', 'm * c') + , ('r * m', 'm * r') + , ('x * nx', 'x * x') + , ('x * nc', 'x * c') + , ('x * nr', 'x * r') + , ('x * nm', 'x * m') + , ('c * nx', 'c * x') + , ('c * nc', 'c * c') + , ('c * nm', 'c * m') + , ('r * nx', 'r * x') + , ('r * nr', 'r * r') + , ('r * nm', 'r * m') + , ('m * nx', 'm * x') + , ('m * nc', 'm * c') + , ('m * nr', 'm * r') + , ('m * nm', 'm * m') + + , ('m.T', 'nm.T') + , ('m.T', 'nm.T') + , ('row.T', 'nrow.T') + , ('m @ m.T', 'nm @ nm.T') + , ('m @ nm.T', 'nm @ nm.T') + , ('row @ row.T', 'nrow @ nrow.T') + , ('row @ nrow.T', 'nrow @ nrow.T') + , ('m.T @ m', 'nm.T @ nm') + , ('m.T @ nm', 'nm.T @ nm') + , ('row.T @ row', 'nrow.T @ nrow') + , ('row.T @ nrow', 'nrow.T @ nrow') + ] +) +def test_block_matrix_elementwise_arithmetic(block_matrix_bindings, x, y): + lhs = eval(x, block_matrix_bindings) + rhs = eval(y, { 'np': np }, block_matrix_bindings) + _assert_eq(lhs, rhs) + + +@pytest.mark.parametrize( + 'x, y', + [ # division + ('x / e', 'nx / e') + , ('c / e', 'nc / e') + , ('r / e', 'nr / e') + , ('m / e', 'nm / e') + , ('x / e', '1 / (e / x)') + , ('c / e', '1 / (e / c)') + , ('r / e', '1 / (e / r)') + , ('m / e', '1 / (e / m)') + , ('x / x', 'np.ones((1, 1))') + , ('c / c', 'np.ones((2, 1))') + , ('r / r', 'np.ones((1, 3))') + , ('m / m', 'np.ones((2, 3))') + , ('x / c', 'np.array([[2 / 1.0], [2 / 2.0]])') + , ('x / r', 'np.array([[2 / 1.0, 2 / 2.0, 2 / 3.0]])') + , ('x / m', 'np.array([[2 / 1.0, 2 / 2.0, 2 / 3.0], [2 / 4.0, 2 / 5.0, 2 / 6.0]])') + , ('c / m', 'np.array([[1 / 1.0, 1 / 2.0, 1 / 3.0], [2 / 4.0, 2 / 5.0, 2 / 6.0]])') + , ('r / m', 'np.array([[1 / 1.0, 2 / 2.0, 3 / 3.0], [1 / 4.0, 2 / 5.0, 3 / 6.0]])') + , ('x / c', '1 / (c / x)') + , ('x / r', '1 / (r / x)') + , ('x / m', '1 / (m / x)') + , ('c / m', '1 / (m / c)') + , ('r / m', '1 / (m / r)') + , ('x / nx', 'x / x') + , ('x / nc', 'x / c') + , ('x / nr', 'x / r') + , ('x / nm', 'x / m') + , ('c / nx', 'c / x') + , ('c / nc', 'c / c') + , ('c / nm', 'c / m') + , ('r / nx', 'r / x') + , ('r / nr', 'r / r') + , ('r / nm', 'r / m') + , ('m / nx', 'm / x') + , ('m / nc', 'm / c') + , ('m / nr', 'm / r') + , ('m / nm', 'm / m') + + # other ops + , ('m ** 3' , 'nm ** 3') + , ('m.sqrt()' , 'np.sqrt(nm)') + , ('m.ceil()' , 'np.ceil(nm)') + , ('m.floor()' , 'np.floor(nm)') + , ('m.log()' , 'np.log(nm)') + , ('(m - 4).abs()', 'np.abs(nm - 4)') + ] +) +def test_block_matrix_elementwise_close_arithmetic(block_matrix_bindings, x, y): + lhs = eval(x, block_matrix_bindings) + rhs = eval(y, { 'np': np }, block_matrix_bindings) + _assert_close(lhs, rhs) + + +@pytest.mark.parametrize( + 'expr, expectation', + [ ('x + np.array([\'one\'], dtype=str)', pytest.raises(TypeError)) + , ('m @ m ', pytest.raises(ValueError)) + , ('m @ nm', pytest.raises(ValueError)) + ] +) +def test_block_matrix_raises(block_matrix_bindings, expr, expectation): + with expectation: + eval(expr, { 'np': np }, block_matrix_bindings) + + +@pytest.mark.parametrize( + 'x, y', + [ ( 'm.sum(axis=0).T' + , 'np.array([[5.0], [7.0], [9.0]])' + ) + , ( 'm.sum(axis=1).T' + , 'np.array([[6.0, 15.0]])' + ) + , ( 'm.sum(axis=0).T + row' + , 'np.array([[12.0, 13.0, 14.0],[14.0, 15.0, 16.0],[16.0, 17.0, 18.0]])' + ) + , ( 'm.sum(axis=0) + row.T' + , 'np.array([[12.0, 14.0, 16.0],[13.0, 15.0, 17.0],[14.0, 16.0, 18.0]])' + ) + , ( 'square.sum(axis=0).T + square.sum(axis=1)' + , 'np.array([[18.0], [30.0], [42.0]])' + ) + ] +) +def test_matrix_sums(block_matrix_bindings, x, y): + lhs = eval(x, block_matrix_bindings) + rhs = eval(y, { 'np': np }, block_matrix_bindings) + _assert_eq(lhs, rhs) + + +@fails_service_backend() +@fails_local_backend() +@pytest.mark.parametrize( + 'x, y', + [ ('m.tree_matmul(m.T, splits=2)', 'nm @ nm.T') + , ('m.tree_matmul(nm.T, splits=2)', 'nm @ nm.T') + , ('row.tree_matmul(row.T, splits=2)', 'nrow @ nrow.T') + , ('row.tree_matmul(nrow.T, splits=2)', 'nrow @ nrow.T') + , ('m.T.tree_matmul(m, splits=2)', 'nm.T @ nm') + , ('m.T.tree_matmul(nm, splits=2)', 'nm.T @ nm') + , ('row.T.tree_matmul(row, splits=2)', 'nrow.T @ nrow') + , ('row.T.tree_matmul(nrow, splits=2)', 'nrow.T @ nrow') + ] +) +def test_tree_matmul(block_matrix_bindings, x, y): + lhs = eval(x, block_matrix_bindings) + rhs = eval(y, block_matrix_bindings) + _assert_eq(lhs, rhs) + + +@fails_service_backend() +@fails_local_backend() +@pytest.mark.parametrize( + 'nrows,ncols,block_size,split_size', + [ (nrows,ncols,block_size,split_size) + for (nrows, ncols) in [(50, 60), (60, 25)] + for block_size in [7, 10] + for split_size in [2, 9] + ] +) +def test_tree_matmul_splits(block_size, split_size, nrows, ncols): + # Variety of block sizes and splits + ndarray = np.arange(nrows * ncols).reshape((nrows, ncols)) + bm = BlockMatrix.from_numpy(ndarray, block_size) + _assert_eq(bm.tree_matmul(bm.T, splits=split_size), ndarray @ ndarray.T) + + +def test_fill(): + nd = np.ones((3, 5)) + bm = BlockMatrix.fill(3, 5, 1.0) + bm2 = BlockMatrix.fill(3, 5, 1.0, block_size=2) + + assert bm.block_size == BlockMatrix.default_block_size() + assert bm2.block_size == 2 + _assert_eq(bm, nd) + _assert_eq(bm2, nd) + + +def test_sum(): + nd = np.arange(11 * 13, dtype=np.float64).reshape((11, 13)) + bm = BlockMatrix.from_ndarray(hl.literal(nd), block_size=3) + assert_sums_agree(bm, nd) + + +@fails_local_backend +@fails_service_backend(reason='ExecuteContext.scoped requires SparkBackend') +def test_sum_with_sparsify(): + nd = np.zeros(shape=(5, 7)) + nd[2, 4] = 1.0 + nd[2, 5] = 2.0 + nd[3, 4] = 3.0 + nd[3, 5] = 4.0 + + hnd = hl.nd.array(nd) + bm = BlockMatrix.from_ndarray(hnd, block_size=2).sparsify_rectangles([[2, 4, 4, 6]]) + + bm2 = BlockMatrix.from_ndarray(hnd, block_size=2).sparsify_rectangles([[2, 4, 4, 6], [0, 5, 0, 1]]) + + bm3 = BlockMatrix.from_ndarray(hnd, block_size=2).sparsify_rectangles([[2, 4, 4, 6], [0, 1, 0, 7]]) + + nd4 = np.zeros(shape=(5, 7)) + bm4 = BlockMatrix.fill(5, 7, value=0.0, block_size=2).sparsify_rectangles([]) + + assert_sums_agree(bm, nd) + assert_sums_agree(bm2, nd) + assert_sums_agree(bm3, nd) + assert_sums_agree(bm4, nd4) + + +@pytest.mark.parametrize('indices', [(0, 0), (5, 7), (-3, 9), (-8, -10)]) +def test_slicing_0(indices): + nd = np.array(np.arange(0, 80, dtype=float)).reshape(8, 10) + bm = BlockMatrix.from_ndarray(hl.literal(nd), block_size=3) + _assert_eq(bm[indices], nd[indices]) + + +@pytest.mark.parametrize( + 'indices', + [ (slice(0, 8), slice(0, 10)) + , (slice(0, 8, 2), slice(0, 10, 2)) + , (slice(2, 4), slice(5, 7)) + , (slice(-8, -1), slice(-10, -1)) + , (slice(-8, -1, 2), slice(-10, -1, 2)) + , (slice(None, 4, 1), slice(None, 4, 1)) + , (slice(4, None), slice(4, None)) + , (slice(None, None), slice(None, None)) + ] +) +def test_slicing_1(indices): + nd = np.array(np.arange(0, 80, dtype=float)).reshape(8, 10) + bm = BlockMatrix.from_ndarray(hl.literal(nd), block_size=3) + _assert_eq(bm[indices], nd[indices]) + _assert_eq(bm[indices][:, :2], nd[indices][:, :2]) + _assert_eq(bm[indices][:2, :], nd[indices][:2, :]) + + +@pytest.mark.parametrize( + 'indices, axis', + [ ((0, slice(3, 4)) , 0) + , ((1, slice(3, 4)) , 0) + , ((-8, slice(3, 4)), 0) + , ((-1, slice(3, 4)), 0) + , ((slice(3, 4), 0), 1) + , ((slice(3, 4), 1), 1) + , ((slice(3, 4), -8), 1) + , ((slice(3, 4), -1), 1) + ] +) +def test_slicing_2(indices, axis): + nd = np.array(np.arange(0, 80, dtype=float)).reshape(8, 10) + bm = BlockMatrix.from_ndarray(hl.literal(nd), block_size=3) + _assert_eq(bm[indices], np.expand_dims(nd[indices], axis)) + _assert_eq(bm[indices] - bm, nd[indices] - nd) + _assert_eq(bm - bm[indices], nd - nd[indices]) + + +@pytest.mark.parametrize( + 'expr', + [ 'square[0, ]' + , 'square[9, 0]' + , 'square[-9, 0]' + , 'square[0, 11]' + , 'square[0, -11]' + , 'square[::-1, 0]' + , 'square[0, ::-1]' + , 'square[:0, 0]' + , 'square[0, :0]' + , 'square[0:9, 0]' + , 'square[-9:, 0]' + , 'square[:-9, 0]' + , 'square[0, :11]' + , 'square[0, -11:]' + , 'square[0, :-11] ' + ] +) +def test_block_matrix_illegal_indexing(block_matrix_bindings, expr): + with pytest.raises(ValueError): + eval(expr, block_matrix_bindings) + + +def test_diagonal_sparse(): + nd = np.array([[ 1.0, 2.0, 3.0, 4.0], + [ 5.0, 6.0, 7.0, 8.0], + [ 9.0, 10.0, 11.0, 12.0], + [13.0, 14.0, 15.0, 16.0], + [17.0, 18.0, 19.0, 20.0]]) + bm = BlockMatrix.from_numpy(nd, block_size=2) + bm = bm.sparsify_row_intervals([0, 0, 0, 0, 0], [2, 2, 2, 2, 2]) + + # FIXME doesn't work in service, if test_is_sparse works, uncomment below + # .assertTrue(bm.is_sparse) + _assert_eq(bm.diagonal(), np.array([[1.0, 6.0, 0.0, 0.0]])) + + +@fails_service_backend() +@fails_local_backend() +def test_slices_with_sparsify(): + nd = np.array(np.arange(0, 80, dtype=float)).reshape(8, 10) + bm = BlockMatrix.from_numpy(nd, block_size=3) + bm2 = bm.sparsify_row_intervals([0, 0, 0, 0, 0, 0, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0]) + assert bm2[0, 1] == 1.0 + assert bm2[0, 2] == 0.0 + assert bm2[0, 9] == 0.0 + + nd2 = np.zeros(shape=(8, 10)) + nd2[0, 1] = 1.0 + + _assert_eq(bm2[:, :], nd2) + _assert_eq(bm2[:, 1], nd2[:, 1:2]) + _assert_eq(bm2[1, :], nd2[1:2, :]) + _assert_eq(bm2[0:5, 0:5], nd2[0:5, 0:5]) + + +def test_sparsify_row_intervals_0(): + nd = np.array([[ 1.0, 2.0, 3.0, 4.0], + [ 5.0, 6.0, 7.0, 8.0], + [ 9.0, 10.0, 11.0, 12.0], + [13.0, 14.0, 15.0, 16.0]]) + bm = BlockMatrix.from_numpy(nd, block_size=2) + + _assert_eq( + bm.sparsify_row_intervals( + starts=[1, 0, 2, 2], + stops= [2, 0, 3, 4]), + np.array([[ 0., 2., 0., 0.], + [ 0., 0., 0., 0.], + [ 0., 0., 11., 0.], + [ 0., 0., 15., 16.]])) + + _assert_eq( + bm.sparsify_row_intervals( + starts=[1, 0, 2, 2], + stops= [2, 0, 3, 4], + blocks_only=True), + np.array([[ 1., 2., 0., 0.], + [ 5., 6., 0., 0.], + [ 0., 0., 11., 12.], + [ 0., 0., 15., 16.]])) + + +@pytest.mark.parametrize( + 'starts, stops', + [ ([0, 1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7, 8]) + , ([0, 0, 5, 3, 4, 5, 8, 2], [9, 0, 5, 3, 4, 5, 9, 5]) + , ([0, 5, 10, 8, 7, 6, 5, 4], [0, 5, 10, 9, 8, 7, 6, 5]) + ] +) +def test_row_intervals_1(starts, stops): + nd2 = np.random.normal(size=(8, 10)) + bm2 = BlockMatrix.from_numpy(nd2, block_size=3) + actual = bm2.sparsify_row_intervals(starts, stops, blocks_only=False).to_numpy() + expected = nd2.copy() + for i in range(0, 8): + for j in range(0, starts[i]): + expected[i, j] = 0.0 + for j in range(stops[i], 10): + expected[i, j] = 0.0 + _assert_eq(actual, expected) + + +def test_sparsify_band_0(): + nd = np.array([[ 1.0, 2.0, 3.0, 4.0], + [ 5.0, 6.0, 7.0, 8.0], + [ 9.0, 10.0, 11.0, 12.0], + [13.0, 14.0, 15.0, 16.0]]) + bm = BlockMatrix.from_numpy(nd, block_size=2) + + _assert_eq( + bm.sparsify_band(lower=-1, upper=2), + np.array([[ 1., 2., 3., 0.], + [ 5., 6., 7., 8.], + [ 0., 10., 11., 12.], + [ 0., 0., 15., 16.]])) + + _assert_eq( + bm.sparsify_band(lower=0, upper=0, blocks_only=True), + np.array([[ 1., 2., 0., 0.], + [ 5., 6., 0., 0.], + [ 0., 0., 11., 12.], + [ 0., 0., 15., 16.]])) + + +@pytest.mark.parametrize( + 'lower, upper', + [ (0, 0), (1, 1), (2, 2), (-5, 5), (-7, 0), (0, 9), (-100, 100) ] +) +def test_sparsify_band_1(lower, upper): + nd2 = np.arange(0, 80, dtype=float).reshape(8, 10) + bm2 = BlockMatrix.from_numpy(nd2, block_size=3) + actual = bm2.sparsify_band(lower, upper, blocks_only=False).to_numpy() + mask = np.fromfunction(lambda i, j: (lower <= j - i) * (j - i <= upper), (8, 10)) + _assert_eq(actual, nd2 * mask) + + +def test_sparsify_triangle(): + nd = np.array([[ 1.0, 2.0, 3.0, 4.0], + [ 5.0, 6.0, 7.0, 8.0], + [ 9.0, 10.0, 11.0, 12.0], + [13.0, 14.0, 15.0, 16.0]]) + bm = BlockMatrix.from_numpy(nd, block_size=2) + + # FIXME doesn't work in service, if test_is_sparse works, uncomment below + # assert not bm.is_sparse + # assert bm.sparsify_triangle().is_sparse + + _assert_eq( + bm.sparsify_triangle(), + np.array([[ 1., 2., 3., 4.], + [ 0., 6., 7., 8.], + [ 0., 0., 11., 12.], + [ 0., 0., 0., 16.]])) + + _assert_eq( + bm.sparsify_triangle(lower=True), + np.array([[ 1., 0., 0., 0.], + [ 5., 6., 0., 0.], + [ 9., 10., 11., 0.], + [13., 14., 15., 16.]])) + + _assert_eq( + bm.sparsify_triangle(blocks_only=True), + np.array([[ 1., 2., 3., 4.], + [ 5., 6., 7., 8.], + [ 0., 0., 11., 12.], + [ 0., 0., 15., 16.]])) + + +def test_sparsify_rectangles(): + nd = np.array([[ 1.0, 2.0, 3.0, 4.0], + [ 5.0, 6.0, 7.0, 8.0], + [ 9.0, 10.0, 11.0, 12.0], + [13.0, 14.0, 15.0, 16.0]]) + bm = BlockMatrix.from_numpy(nd, block_size=2) + + _assert_eq( + bm.sparsify_rectangles([[0, 1, 0, 1], [0, 3, 0, 2], [1, 2, 0, 4]]), + np.array([[ 1., 2., 3., 4.], + [ 5., 6., 7., 8.], + [ 9., 10., 0., 0.], + [13., 14., 0., 0.]])) + + _assert_eq(bm.sparsify_rectangles([]), np.zeros(shape=(4, 4))) + + +@fails_service_backend() +@fails_local_backend() +@pytest.mark.parametrize( + 'rects,block_size,binary', + [ (rects, block_size, binary) + for binary in [False, True] + for block_size in [3, 4, 10] + for rects in + [ [ [0, 1, 0, 1] + , [4, 5, 7, 8] + ] + , [ [4, 5, 0, 10] + , [0, 8, 4, 5] + ] + , [ [0, 1, 0, 1] + , [1, 2, 1, 2] + , [2, 3, 2, 3] + , [3, 5, 3, 6] + , [3, 6, 3, 7] + , [3, 7, 3, 8] + , [4, 5, 0, 10] + , [0, 8, 4, 5] + , [0, 8, 0, 10] + ] + ] + ] +) +def test_export_rectangles(rects, block_size, binary): + nd = np.arange(0, 80, dtype=float).reshape(8, 10) + bm = BlockMatrix.from_numpy(nd, block_size=block_size) + with hl.TemporaryDirectory() as rect_uri: + bm.export_rectangles(rect_uri, rects, binary=binary) + _assert_rectangles_eq(nd, rect_uri, rects, binary=binary) + + +@fails_service_backend() +@fails_local_backend() +def test_export_rectangles_sparse(): + with hl.TemporaryDirectory() as rect_uri: + nd = np.array([[1.0, 2.0, 3.0, 4.0], + [5.0, 6.0, 7.0, 8.0], + [9.0, 10.0, 11.0, 12.0], + [13.0, 14.0, 15.0, 16.0]]) bm = BlockMatrix.from_numpy(nd, block_size=2) - bm = bm.sparsify_row_intervals([0, 0, 0, 0, 0], [2, 2, 2, 2, 2]) + sparsify_rects = [[0, 1, 0, 1], [0, 3, 0, 2], [1, 2, 0, 4]] + export_rects = [[0, 1, 0, 1], [0, 3, 0, 2], [1, 2, 0, 4], [2, 4, 2, 4]] + bm.sparsify_rectangles(sparsify_rects).export_rectangles(rect_uri, export_rects) - # FIXME doesn't work in service, if test_is_sparse works, uncomment below - # self.assertTrue(bm.is_sparse) - self._assert_eq(bm.diagonal(), np.array([[1.0, 6.0, 0.0, 0.0]])) + expected = np.array([[1.0, 2.0, 3.0, 4.0], + [5.0, 6.0, 7.0, 8.0], + [9.0, 10.0, 0.0, 0.0], + [13.0, 14.0, 0.0, 0.0]]) - @fails_service_backend() - @fails_local_backend() - def test_slices_with_sparsify(self): - nd = np.array(np.arange(0, 80, dtype=float)).reshape(8, 10) - bm = BlockMatrix.from_numpy(nd, block_size=3) - bm2 = bm.sparsify_row_intervals([0, 0, 0, 0, 0, 0, 0, 0], [2, 0, 0, 0, 0, 0, 0, 0]) - self.assertEqual(bm2[0, 1], 1.0) - self.assertEqual(bm2[0, 2], 0.0) - self.assertEqual(bm2[0, 9], 0.0) + _assert_rectangles_eq(expected, rect_uri, export_rects) - nd2 = np.zeros(shape=(8, 10)) - nd2[0, 1] = 1.0 - with BatchedAsserts() as b: +@fails_service_backend() +@fails_local_backend() +def test_export_rectangles_filtered(): + with hl.TemporaryDirectory() as rect_uri: + nd = np.array([[1.0, 2.0, 3.0, 4.0], + [5.0, 6.0, 7.0, 8.0], + [9.0, 10.0, 11.0, 12.0], + [13.0, 14.0, 15.0, 16.0]]) + bm = BlockMatrix.from_numpy(nd) + bm = bm[1:3, 1:3] + export_rects = [[0, 1, 0, 2], [1, 2, 0, 2]] + bm.export_rectangles(rect_uri, export_rects) + + expected = np.array([[6.0, 7.0], + [10.0, 11.0]]) + + _assert_rectangles_eq(expected, rect_uri, export_rects) + + +@fails_service_backend() +@fails_local_backend() +def test_export_blocks(): + nd = np.ones(shape=(8, 10)) + bm = BlockMatrix.from_numpy(nd, block_size=20) + + with hl.TemporaryDirectory() as bm_uri: + bm.export_blocks(bm_uri, binary=True) + actual = BlockMatrix.rectangles_to_numpy(bm_uri, binary=True) + _assert_eq(nd, actual) + + +@fails_service_backend() +@fails_local_backend() +@pytest.mark.parametrize('binary', [True, False]) +def test_rectangles_to_numpy(binary): + nd = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]) + rects = [[0, 3, 0, 1], [1, 2, 0, 2]] + expected = np.array([[1.0, 0.0], [4.0, 5.0], [7.0, 0.0]]) + with hl.TemporaryDirectory() as rect_uri: + BlockMatrix.from_numpy(nd).export_rectangles(rect_uri, rects, binary=binary) + _assert_eq(expected, BlockMatrix.rectangles_to_numpy(rect_uri, binary=binary)) - b.assert_eq(bm2[:, :], nd2) - b.assert_eq(bm2[:, 1], nd2[:, 1:2]) - b.assert_eq(bm2[1, :], nd2[1:2, :]) - b.assert_eq(bm2[0:5, 0:5], nd2[0:5, 0:5]) +def test_to_ndarray(): + np_mat = np.arange(12).reshape((4, 3)).astype(np.float64) + mat = BlockMatrix.from_ndarray(hl.nd.array(np_mat)).to_ndarray() + assert np.array_equal(np_mat, hl.eval(mat)) - def test_sparsify_row_intervals(self): - nd = np.array([[ 1.0, 2.0, 3.0, 4.0], - [ 5.0, 6.0, 7.0, 8.0], - [ 9.0, 10.0, 11.0, 12.0], - [13.0, 14.0, 15.0, 16.0]]) - bm = BlockMatrix.from_numpy(nd, block_size=2) + blocks_to_sparsify = [1, 4, 7, 12, 20, 42, 48] + sparsed_numpy = sparsify_numpy(np.arange(25*25).reshape((25, 25)), 4, blocks_to_sparsify) + sparsed = BlockMatrix.from_ndarray(hl.nd.array(sparsed_numpy), block_size=4)._sparsify_blocks(blocks_to_sparsify).to_ndarray() + assert np.array_equal(sparsed_numpy, hl.eval(sparsed)) - with BatchedAsserts() as b: - - b.assert_eq( - bm.sparsify_row_intervals( - starts=[1, 0, 2, 2], - stops= [2, 0, 3, 4]), - np.array([[ 0., 2., 0., 0.], - [ 0., 0., 0., 0.], - [ 0., 0., 11., 0.], - [ 0., 0., 15., 16.]])) - - b.assert_eq( - bm.sparsify_row_intervals( - starts=[1, 0, 2, 2], - stops= [2, 0, 3, 4], - blocks_only=True), - np.array([[ 1., 2., 0., 0.], - [ 5., 6., 0., 0.], - [ 0., 0., 11., 12.], - [ 0., 0., 15., 16.]])) - - nd2 = np.random.normal(size=(8, 10)) - bm2 = BlockMatrix.from_numpy(nd2, block_size=3) - - for bounds in [[[0, 1, 2, 3, 4, 5, 6, 7], - [1, 2, 3, 4, 5, 6, 7, 8]], - [[0, 0, 5, 3, 4, 5, 8, 2], - [9, 0, 5, 3, 4, 5, 9, 5]], - [[0, 5, 10, 8, 7, 6, 5, 4], - [0, 5, 10, 9, 8, 7, 6, 5]]]: - starts, stops = bounds - actual = bm2.sparsify_row_intervals(starts, stops, blocks_only=False).to_numpy() - expected = nd2.copy() - for i in range(0, 8): - for j in range(0, starts[i]): - expected[i, j] = 0.0 - for j in range(stops[i], 10): - expected[i, j] = 0.0 - b.assert_eq(actual, expected) - - def test_sparsify_band(self): - nd = np.array([[ 1.0, 2.0, 3.0, 4.0], - [ 5.0, 6.0, 7.0, 8.0], - [ 9.0, 10.0, 11.0, 12.0], - [13.0, 14.0, 15.0, 16.0]]) - bm = BlockMatrix.from_numpy(nd, block_size=2) - with BatchedAsserts() as b: - - b.assert_eq( - bm.sparsify_band(lower=-1, upper=2), - np.array([[ 1., 2., 3., 0.], - [ 5., 6., 7., 8.], - [ 0., 10., 11., 12.], - [ 0., 0., 15., 16.]])) - - b.assert_eq( - bm.sparsify_band(lower=0, upper=0, blocks_only=True), - np.array([[ 1., 2., 0., 0.], - [ 5., 6., 0., 0.], - [ 0., 0., 11., 12.], - [ 0., 0., 15., 16.]])) - - nd2 = np.arange(0, 80, dtype=float).reshape(8, 10) - bm2 = BlockMatrix.from_numpy(nd2, block_size=3) - - for bounds in [[0, 0], [1, 1], [2, 2], [-5, 5], [-7, 0], [0, 9], [-100, 100]]: - lower, upper = bounds - actual = bm2.sparsify_band(lower, upper, blocks_only=False).to_numpy() - mask = np.fromfunction(lambda i, j: (lower <= j - i) * (j - i <= upper), (8, 10)) - b.assert_eq(actual, nd2 * mask) - - def test_sparsify_triangle(self): - nd = np.array([[ 1.0, 2.0, 3.0, 4.0], - [ 5.0, 6.0, 7.0, 8.0], - [ 9.0, 10.0, 11.0, 12.0], - [13.0, 14.0, 15.0, 16.0]]) - bm = BlockMatrix.from_numpy(nd, block_size=2) +@test_timeout(batch=5 * 60) +@pytest.mark.parametrize('block_size', [1, 2, 1024]) +def test_block_matrix_entries(block_size): + n_rows, n_cols = 5, 3 + rows = [{'i': i, 'j': j, 'entry': float(i + j)} for i in range(n_rows) for j in range(n_cols)] + schema = hl.tstruct(i=hl.tint32, j=hl.tint32, entry=hl.tfloat64) + table = hl.Table.parallelize( + [hl.struct(i=row['i'], j=row['j'], entry=row['entry']) for row in rows], + schema + ) + table = table.annotate(i=hl.int64(table.i), j=hl.int64(table.j)).key_by('i', 'j') - # FIXME doesn't work in service, if test_is_sparse works, uncomment below - # self.assertFalse(bm.is_sparse) - # self.assertTrue(bm.sparsify_triangle().is_sparse) - - with BatchedAsserts() as b: - - b.assert_eq( - bm.sparsify_triangle(), - np.array([[ 1., 2., 3., 4.], - [ 0., 6., 7., 8.], - [ 0., 0., 11., 12.], - [ 0., 0., 0., 16.]])) - - b.assert_eq( - bm.sparsify_triangle(lower=True), - np.array([[ 1., 0., 0., 0.], - [ 5., 6., 0., 0.], - [ 9., 10., 11., 0.], - [13., 14., 15., 16.]])) - - b.assert_eq( - bm.sparsify_triangle(blocks_only=True), - np.array([[ 1., 2., 3., 4.], - [ 5., 6., 7., 8.], - [ 0., 0., 11., 12.], - [ 0., 0., 15., 16.]])) - - def test_sparsify_rectangles(self): - nd = np.array([[ 1.0, 2.0, 3.0, 4.0], - [ 5.0, 6.0, 7.0, 8.0], - [ 9.0, 10.0, 11.0, 12.0], - [13.0, 14.0, 15.0, 16.0]]) - bm = BlockMatrix.from_numpy(nd, block_size=2) + ndarray = np.reshape(list(map(lambda row: row['entry'], rows)), (n_rows, n_cols)) + + block_matrix = BlockMatrix.from_ndarray(hl.literal(ndarray), block_size) + entries_table = block_matrix.entries() + assert entries_table.count() == n_cols * n_rows + assert len(entries_table.row) == 3 + assert table._same(entries_table) + + +def test_from_entry_expr_filtered(): + mt = hl.utils.range_matrix_table(1, 1).filter_entries(False) + bm = hl.linalg.BlockMatrix.from_entry_expr(mt.row_idx + mt.col_idx, mean_impute=True) # should run without error + assert np.isnan(bm.entries().entry.collect()[0]) + +def test_array_windows(): + def assert_eq(a, b): + assert np.array_equal(a, np.array(b)) + + starts, stops = hl.linalg.utils.array_windows(np.array([1, 2, 4, 4, 6, 8]), 2) + assert_eq(starts, [0, 0, 1, 1, 2, 4]) + assert_eq(stops, [2, 4, 5, 5, 6, 6]) + + starts, stops = hl.linalg.utils.array_windows(np.array([-10.0, -2.5, 0.0, 0.0, 1.2, 2.3, 3.0]), 2.5) + assert_eq(starts, [0, 1, 1, 1, 2, 2, 4]) + assert_eq(stops, [1, 4, 6, 6, 7, 7, 7]) + + starts, stops = hl.linalg.utils.array_windows(np.array([0, 0, 1]), 0) + assert_eq(starts, [0, 0, 2]) + assert_eq(stops, [2, 2, 3]) + + starts, stops = hl.linalg.utils.array_windows(np.array([]), 1) + assert starts.size == 0 + assert stops.size == 0 + + starts, stops = hl.linalg.utils.array_windows(np.array([-float('inf'), -1, 0, 1, float("inf")]), 1) + assert_eq(starts, [0, 1, 1, 2, 4]) + assert_eq(stops, [1, 3, 4, 4, 5]) + + +@pytest.mark.parametrize( + 'array,radius', + [ ([1, 0], -1) + , ([0, float('nan')], 1) + , ([float('nan')], 1) + , ([0.0, float('nan')], 1) + , ([None], 1) + , ([], -1) + , (['str'], 1) + ] +) +def test_array_windows_illegal_arguments(array, radius): + with pytest.raises(ValueError): + hl.linalg.utils.array_windows(np.array(array), radius) + + +def test_locus_windows_per_contig(): + f = hl._locus_windows_per_contig([[1.0, 3.0, 4.0], [2.0, 2.0], [5.0]], 1.0) + assert hl.eval(f) == ([0, 1, 1, 3, 3, 5], [1, 3, 3, 5, 5, 6]) + + +def test_locus_windows_1(): + centimorgans = hl.literal([0.1, 1.0, 1.0, 1.5, 1.9]) + + mt = hl.balding_nichols_model(1, 5, 5).add_row_index() + mt = mt.annotate_rows(cm=centimorgans[hl.int32(mt.row_idx)]).cache() + + starts, stops = hl.linalg.utils.locus_windows(mt.locus, 2) + assert_np_arrays_eq(starts, [0, 0, 0, 1, 2]) + assert_np_arrays_eq(stops, [3, 4, 5, 5, 5]) + + +def test_locus_windows_2(): + centimorgans = hl.literal([0.1, 1.0, 1.0, 1.5, 1.9]) - with BatchedAsserts() as b: - - b.assert_eq( - bm.sparsify_rectangles([[0, 1, 0, 1], [0, 3, 0, 2], [1, 2, 0, 4]]), - np.array([[ 1., 2., 3., 4.], - [ 5., 6., 7., 8.], - [ 9., 10., 0., 0.], - [13., 14., 0., 0.]])) - - b.assert_eq(bm.sparsify_rectangles([]), np.zeros(shape=(4, 4))) - - @fails_service_backend() - @fails_local_backend() - def test_export_rectangles(self): - nd = np.arange(0, 80, dtype=float).reshape(8, 10) - - rects1 = [[0, 1, 0, 1], [4, 5, 7, 8]] - - rects2 = [[4, 5, 0, 10], [0, 8, 4, 5]] - - rects3 = [[0, 1, 0, 1], [1, 2, 1, 2], [2, 3, 2, 3], - [3, 5, 3, 6], [3, 6, 3, 7], [3, 7, 3, 8], - [4, 5, 0, 10], [0, 8, 4, 5], [0, 8, 0, 10]] - - for rects in [rects1, rects2, rects3]: - for block_size in [3, 4, 10]: - with hl.TemporaryDirectory() as rect_uri, hl.TemporaryDirectory() as rect_uri_bytes: - bm = BlockMatrix.from_numpy(nd, block_size=block_size) - - bm.export_rectangles(rect_uri, rects) - self._assert_rectangles_eq(nd, rect_uri, rects) - - bm.export_rectangles(rect_uri_bytes, rects, binary=True) - self._assert_rectangles_eq(nd, rect_uri_bytes, rects, binary=True) - - @fails_service_backend() - @fails_local_backend() - def test_export_rectangles_sparse(self): - with hl.TemporaryDirectory() as rect_uri: - nd = np.array([[1.0, 2.0, 3.0, 4.0], - [5.0, 6.0, 7.0, 8.0], - [9.0, 10.0, 11.0, 12.0], - [13.0, 14.0, 15.0, 16.0]]) - bm = BlockMatrix.from_numpy(nd, block_size=2) - sparsify_rects = [[0, 1, 0, 1], [0, 3, 0, 2], [1, 2, 0, 4]] - export_rects = [[0, 1, 0, 1], [0, 3, 0, 2], [1, 2, 0, 4], [2, 4, 2, 4]] - bm.sparsify_rectangles(sparsify_rects).export_rectangles(rect_uri, export_rects) - - expected = np.array([[1.0, 2.0, 3.0, 4.0], - [5.0, 6.0, 7.0, 8.0], - [9.0, 10.0, 0.0, 0.0], - [13.0, 14.0, 0.0, 0.0]]) - - self._assert_rectangles_eq(expected, rect_uri, export_rects) - - @fails_service_backend() - @fails_local_backend() - def test_export_rectangles_filtered(self): - with hl.TemporaryDirectory() as rect_uri: - nd = np.array([[1.0, 2.0, 3.0, 4.0], - [5.0, 6.0, 7.0, 8.0], - [9.0, 10.0, 11.0, 12.0], - [13.0, 14.0, 15.0, 16.0]]) - bm = BlockMatrix.from_numpy(nd) - bm = bm[1:3, 1:3] - export_rects = [[0, 1, 0, 2], [1, 2, 0, 2]] - bm.export_rectangles(rect_uri, export_rects) - - expected = np.array([[6.0, 7.0], - [10.0, 11.0]]) - - self._assert_rectangles_eq(expected, rect_uri, export_rects) - - @fails_service_backend() - @fails_local_backend() - def test_export_blocks(self): - nd = np.ones(shape=(8, 10)) - bm = BlockMatrix.from_numpy(nd, block_size=20) - - with hl.TemporaryDirectory() as bm_uri: - bm.export_blocks(bm_uri, binary=True) - actual = BlockMatrix.rectangles_to_numpy(bm_uri, binary=True) - self._assert_eq(nd, actual) - - @fails_service_backend() - @fails_local_backend() - def test_rectangles_to_numpy(self): - nd = np.array([[1.0, 2.0, 3.0], - [4.0, 5.0, 6.0], - [7.0, 8.0, 9.0]]) - - rects = [[0, 3, 0, 1], [1, 2, 0, 2]] - - with hl.TemporaryDirectory() as rect_uri, hl.TemporaryDirectory() as rect_bytes_uri: - BlockMatrix.from_numpy(nd).export_rectangles(rect_uri, rects) - BlockMatrix.from_numpy(nd).export_rectangles(rect_bytes_uri, rects, binary=True) - - expected = np.array([[1.0, 0.0], - [4.0, 5.0], - [7.0, 0.0]]) - self._assert_eq(expected, BlockMatrix.rectangles_to_numpy(rect_uri)) - self._assert_eq(expected, BlockMatrix.rectangles_to_numpy(rect_bytes_uri, binary=True)) - - def test_to_ndarray(self): - np_mat = np.arange(12).reshape((4, 3)).astype(np.float64) - mat = BlockMatrix.from_ndarray(hl.nd.array(np_mat)).to_ndarray() - self.assertTrue(np.array_equal(np_mat, hl.eval(mat))) - - blocks_to_sparsify = [1, 4, 7, 12, 20, 42, 48] - sparsed_numpy = sparsify_numpy(np.arange(25*25).reshape((25, 25)), 4, blocks_to_sparsify) - sparsed = BlockMatrix.from_ndarray(hl.nd.array(sparsed_numpy), block_size=4)._sparsify_blocks(blocks_to_sparsify).to_ndarray() - self.assertTrue(np.array_equal(sparsed_numpy, hl.eval(sparsed))) - - @test_timeout(batch=5 * 60) - def test_block_matrix_entries(self): - n_rows, n_cols = 5, 3 - rows = [{'i': i, 'j': j, 'entry': float(i + j)} for i in range(n_rows) for j in range(n_cols)] - schema = hl.tstruct(i=hl.tint32, j=hl.tint32, entry=hl.tfloat64) - table = hl.Table.parallelize([hl.struct(i=row['i'], j=row['j'], entry=row['entry']) for row in rows], schema) - table = table.annotate(i=hl.int64(table.i), - j=hl.int64(table.j)).key_by('i', 'j') - - ndarray = np.reshape(list(map(lambda row: row['entry'], rows)), (n_rows, n_cols)) - - for block_size in [1, 2, 1024]: - block_matrix = BlockMatrix.from_ndarray(hl.literal(ndarray), block_size) - entries_table = block_matrix.entries() - self.assertEqual(entries_table.count(), n_cols * n_rows) - self.assertEqual(len(entries_table.row), 3) - self.assertTrue(table._same(entries_table)) - - def test_from_entry_expr_filtered(self): - mt = hl.utils.range_matrix_table(1, 1).filter_entries(False) - bm = hl.linalg.BlockMatrix.from_entry_expr(mt.row_idx + mt.col_idx, mean_impute=True) # should run without error - assert np.isnan(bm.entries().entry.collect()[0]) - - def test_array_windows(self): - def assert_eq(a, b): - self.assertTrue(np.array_equal(a, np.array(b))) - - starts, stops = hl.linalg.utils.array_windows(np.array([1, 2, 4, 4, 6, 8]), 2) - assert_eq(starts, [0, 0, 1, 1, 2, 4]) - assert_eq(stops, [2, 4, 5, 5, 6, 6]) - - starts, stops = hl.linalg.utils.array_windows(np.array([-10.0, -2.5, 0.0, 0.0, 1.2, 2.3, 3.0]), 2.5) - assert_eq(starts, [0, 1, 1, 1, 2, 2, 4]) - assert_eq(stops, [1, 4, 6, 6, 7, 7, 7]) - - starts, stops = hl.linalg.utils.array_windows(np.array([0, 0, 1]), 0) - assert_eq(starts, [0, 0, 2]) - assert_eq(stops, [2, 2, 3]) - - starts, stops = hl.linalg.utils.array_windows(np.array([]), 1) - self.assertEqual(starts.size, 0) - self.assertEqual(stops.size, 0) - - starts, stops = hl.linalg.utils.array_windows(np.array([-float('inf'), -1, 0, 1, float("inf")]), 1) - assert_eq(starts, [0, 1, 1, 2, 4]) - assert_eq(stops, [1, 3, 4, 4, 5]) - - self.assertRaises(ValueError, lambda: hl.linalg.utils.array_windows(np.array([1, 0]), -1)) - self.assertRaises(ValueError, lambda: hl.linalg.utils.array_windows(np.array([0, float('nan')]), 1)) - self.assertRaises(ValueError, lambda: hl.linalg.utils.array_windows(np.array([float('nan')]), 1)) - self.assertRaises(ValueError, lambda: hl.linalg.utils.array_windows(np.array([0.0, float('nan')]), 1)) - self.assertRaises(ValueError, lambda: hl.linalg.utils.array_windows(np.array([None]), 1)) - self.assertRaises(ValueError, lambda: hl.linalg.utils.array_windows(np.array([]), -1)) - self.assertRaises(ValueError, lambda: hl.linalg.utils.array_windows(np.array(['str']), 1)) - - def test_locus_windows_per_contig(self): - f = hl._locus_windows_per_contig([[1.0, 3.0, 4.0], [2.0, 2.0], [5.0]], 1.0) - assert hl.eval(f) == ([0, 1, 1, 3, 3, 5], [1, 3, 3, 5, 5, 6]) - - def assert_np_arrays_eq(self, a, b): - assert np.array_equal(a, np.array(b)), f"a={a}, b={b}" - - def test_locus_windows_1(self): - centimorgans = hl.literal([0.1, 1.0, 1.0, 1.5, 1.9]) - - mt = hl.balding_nichols_model(1, 5, 5).add_row_index() - mt = mt.annotate_rows(cm=centimorgans[hl.int32(mt.row_idx)]).cache() - - starts, stops = hl.linalg.utils.locus_windows(mt.locus, 2) - self.assert_np_arrays_eq(starts, [0, 0, 0, 1, 2]) - self.assert_np_arrays_eq(stops, [3, 4, 5, 5, 5]) - - def test_locus_windows_2(self): - centimorgans = hl.literal([0.1, 1.0, 1.0, 1.5, 1.9]) - - mt = hl.balding_nichols_model(1, 5, 5).add_row_index() - mt = mt.annotate_rows(cm=centimorgans[hl.int32(mt.row_idx)]).cache() - - starts, stops = hl.linalg.utils.locus_windows(mt.locus, 0.5, coord_expr=mt.cm) - self.assert_np_arrays_eq(starts, [0, 1, 1, 1, 3]) - self.assert_np_arrays_eq(stops, [1, 4, 4, 5, 5]) - - def test_locus_windows_3(self): - centimorgans = hl.literal([0.1, 1.0, 1.0, 1.5, 1.9]) - - mt = hl.balding_nichols_model(1, 5, 5).add_row_index() - mt = mt.annotate_rows(cm=centimorgans[hl.int32(mt.row_idx)]).cache() - - starts, stops = hl.linalg.utils.locus_windows(mt.locus, 1.0, coord_expr=2 * centimorgans[hl.int32(mt.row_idx)]) - self.assert_np_arrays_eq(starts, [0, 1, 1, 1, 3]) - self.assert_np_arrays_eq(stops, [1, 4, 4, 5, 5]) - - def test_locus_windows_4(self): - rows = [{'locus': hl.Locus('1', 1), 'cm': 1.0}, - {'locus': hl.Locus('1', 2), 'cm': 3.0}, - {'locus': hl.Locus('1', 4), 'cm': 4.0}, - {'locus': hl.Locus('2', 1), 'cm': 2.0}, - {'locus': hl.Locus('2', 1), 'cm': 2.0}, - {'locus': hl.Locus('3', 3), 'cm': 5.0}] - - ht = hl.Table.parallelize(rows, - hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), - key=['locus']) - - starts, stops = hl.linalg.utils.locus_windows(ht.locus, 1) - self.assert_np_arrays_eq(starts, [0, 0, 2, 3, 3, 5]) - self.assert_np_arrays_eq(stops, [2, 2, 3, 5, 5, 6]) - - def dummy_table_with_loci_and_cms(self): - rows = [{'locus': hl.Locus('1', 1), 'cm': 1.0}, - {'locus': hl.Locus('1', 2), 'cm': 3.0}, - {'locus': hl.Locus('1', 4), 'cm': 4.0}, - {'locus': hl.Locus('2', 1), 'cm': 2.0}, - {'locus': hl.Locus('2', 1), 'cm': 2.0}, - {'locus': hl.Locus('3', 3), 'cm': 5.0}] - - return hl.Table.parallelize(rows, - hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), - key=['locus']) - - def test_locus_windows_5(self): - ht = self.dummy_table_with_loci_and_cms() - starts, stops = hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=ht.cm) - self.assert_np_arrays_eq(starts, [0, 1, 1, 3, 3, 5]) - self.assert_np_arrays_eq(stops, [1, 3, 3, 5, 5, 6]) - - def test_locus_windows_6(self): - ht = self.dummy_table_with_loci_and_cms() - with self.assertRaises(HailUserError) as cm: - hl.linalg.utils.locus_windows(ht.order_by(ht.cm).locus, 1.0) - assert 'ascending order' in str(cm.exception) - - def test_locus_windows_7(self): - ht = self.dummy_table_with_loci_and_cms() - with self.assertRaises(ExpressionException) as cm: - hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=hl.utils.range_table(1).idx) - assert 'different source' in str(cm.exception) - - def test_locus_windows_8(self): - ht = self.dummy_table_with_loci_and_cms() - with self.assertRaises(ExpressionException) as cm: - hl.linalg.utils.locus_windows(hl.locus('1', 1), 1.0) - assert "no source" in str(cm.exception) - - def test_locus_windows_9(self): - ht = self.dummy_table_with_loci_and_cms() - with self.assertRaises(ExpressionException) as cm: - hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=0.0) - assert "no source" in str(cm.exception) - - def test_locus_windows_10(self): - ht = self.dummy_table_with_loci_and_cms() - ht = ht.annotate_globals(x = hl.locus('1', 1), y = 1.0) - with self.assertRaises(ExpressionException) as cm: - hl.linalg.utils.locus_windows(ht.x, 1.0) - assert "row-indexed" in str(cm.exception) - - with self.assertRaises(ExpressionException) as cm: - hl.linalg.utils.locus_windows(ht.locus, 1.0, ht.y) - assert "row-indexed" in str(cm.exception) - - def test_locus_windows_11(self): - ht = hl.Table.parallelize([{'locus': hl.missing(hl.tlocus()), 'cm': 1.0}], - hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), key=['locus']) - with self.assertRaises(HailUserError) as cm: - hl.linalg.utils.locus_windows(ht.locus, 1.0) - assert "missing value for 'locus_expr'" in str(cm.exception) - - with self.assertRaises(HailUserError) as cm: - hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=ht.cm) - assert "missing value for 'locus_expr'" in str(cm.exception) - - def test_locus_windows_12(self): - ht = hl.Table.parallelize([{'locus': hl.Locus('1', 1), 'cm': hl.missing(hl.tfloat64)}], - hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), key=['locus']) - with self.assertRaises(FatalError) as cm: - hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=ht.cm) - assert "missing value for 'coord_expr'" in str(cm.exception) - - def test_write_overwrite(self): - with hl.TemporaryDirectory(ensure_exists=False) as path: - bm = BlockMatrix.from_numpy(np.array([[0]])) + mt = hl.balding_nichols_model(1, 5, 5).add_row_index() + mt = mt.annotate_rows(cm=centimorgans[hl.int32(mt.row_idx)]).cache() + + starts, stops = hl.linalg.utils.locus_windows(mt.locus, 0.5, coord_expr=mt.cm) + assert_np_arrays_eq(starts, [0, 1, 1, 1, 3]) + assert_np_arrays_eq(stops, [1, 4, 4, 5, 5]) + + +def test_locus_windows_3(): + centimorgans = hl.literal([0.1, 1.0, 1.0, 1.5, 1.9]) + + mt = hl.balding_nichols_model(1, 5, 5).add_row_index() + mt = mt.annotate_rows(cm=centimorgans[hl.int32(mt.row_idx)]).cache() + + starts, stops = hl.linalg.utils.locus_windows(mt.locus, 1.0, coord_expr=2 * centimorgans[hl.int32(mt.row_idx)]) + assert_np_arrays_eq(starts, [0, 1, 1, 1, 3]) + assert_np_arrays_eq(stops, [1, 4, 4, 5, 5]) + + +def test_locus_windows_4(): + rows = [{'locus': hl.Locus('1', 1), 'cm': 1.0}, + {'locus': hl.Locus('1', 2), 'cm': 3.0}, + {'locus': hl.Locus('1', 4), 'cm': 4.0}, + {'locus': hl.Locus('2', 1), 'cm': 2.0}, + {'locus': hl.Locus('2', 1), 'cm': 2.0}, + {'locus': hl.Locus('3', 3), 'cm': 5.0}] + + ht = hl.Table.parallelize(rows, + hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), + key=['locus']) + + starts, stops = hl.linalg.utils.locus_windows(ht.locus, 1) + assert_np_arrays_eq(starts, [0, 0, 2, 3, 3, 5]) + assert_np_arrays_eq(stops, [2, 2, 3, 5, 5, 6]) + + +def dummy_table_with_loci_and_cms(): + rows = [{'locus': hl.Locus('1', 1), 'cm': 1.0}, + {'locus': hl.Locus('1', 2), 'cm': 3.0}, + {'locus': hl.Locus('1', 4), 'cm': 4.0}, + {'locus': hl.Locus('2', 1), 'cm': 2.0}, + {'locus': hl.Locus('2', 1), 'cm': 2.0}, + {'locus': hl.Locus('3', 3), 'cm': 5.0}] + + return hl.Table.parallelize(rows, + hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), + key=['locus']) + + +def test_locus_windows_5(): + ht = dummy_table_with_loci_and_cms() + starts, stops = hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=ht.cm) + assert_np_arrays_eq(starts, [0, 1, 1, 3, 3, 5]) + assert_np_arrays_eq(stops, [1, 3, 3, 5, 5, 6]) + + +def test_locus_windows_6(): + ht = dummy_table_with_loci_and_cms() + with pytest.raises(HailUserError, match='ascending order'): + hl.linalg.utils.locus_windows(ht.order_by(ht.cm).locus, 1.0) + + +def test_locus_windows_7(): + ht = dummy_table_with_loci_and_cms() + with pytest.raises(ExpressionException, match='different source'): + hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=hl.utils.range_table(1).idx) + + +def test_locus_windows_8(): + with pytest.raises(ExpressionException, match='no source'): + hl.linalg.utils.locus_windows(hl.locus('1', 1), 1.0) + + +def test_locus_windows_9(): + ht = dummy_table_with_loci_and_cms() + with pytest.raises(ExpressionException, match='no source'): + hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=0.0) + + +def test_locus_windows_10(): + ht = dummy_table_with_loci_and_cms() + ht = ht.annotate_globals(x = hl.locus('1', 1), y = 1.0) + with pytest.raises(ExpressionException, match='row-indexed'): + hl.linalg.utils.locus_windows(ht.x, 1.0) + + with pytest.raises(ExpressionException, match='row-indexed'): + hl.linalg.utils.locus_windows(ht.locus, 1.0, ht.y) + + +def test_locus_windows_11(): + ht = hl.Table.parallelize([{'locus': hl.missing(hl.tlocus()), 'cm': 1.0}], + hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), key=['locus']) + with pytest.raises(HailUserError, match='missing value for \'locus_expr\''): + hl.linalg.utils.locus_windows(ht.locus, 1.0) + + with pytest.raises(HailUserError, match='missing value for \'locus_expr\''): + hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=ht.cm) + + +def test_locus_windows_12(): + ht = hl.Table.parallelize( + [{'locus': hl.Locus('1', 1), 'cm': hl.missing(hl.tfloat64)}], + hl.tstruct(locus=hl.tlocus('GRCh37'), cm=hl.tfloat64), + key=['locus'] + ) + with pytest.raises(FatalError, match='missing value for \'coord_expr\''): + hl.linalg.utils.locus_windows(ht.locus, 1.0, coord_expr=ht.cm) + + +def test_write_overwrite(): + with hl.TemporaryDirectory(ensure_exists=False) as path: + bm = BlockMatrix.from_numpy(np.array([[0]])) + bm.write(path) + with pytest.raises(FatalError): bm.write(path) - self.assertRaises(FatalError, lambda: bm.write(path)) - - bm2 = BlockMatrix.from_numpy(np.array([[1]])) - bm2.write(path, overwrite=True) - self._assert_eq(BlockMatrix.read(path), bm2) - - def test_stage_locally(self): - nd = np.arange(0, 80, dtype=float).reshape(8, 10) - with hl.TemporaryDirectory(ensure_exists=False) as bm_uri: - BlockMatrix.from_numpy(nd, block_size=3).write(bm_uri, stage_locally=True) - - bm = BlockMatrix.read(bm_uri) - self._assert_eq(nd, bm) - - def test_svd(self): - def assert_same_columns_up_to_sign(a, b): - for j in range(a.shape[1]): - assert np.allclose(a[:, j], b[:, j]) or np.allclose(-a[:, j], b[:, j]) - - x0 = np.array([[-2.0, 0.0, 3.0], - [-1.0, 2.0, 4.0]]) - u0, s0, vt0 = np.linalg.svd(x0, full_matrices=False) - - x = BlockMatrix.from_numpy(x0) - - # _svd - u, s, vt = x.svd() - assert_same_columns_up_to_sign(u, u0) - assert np.allclose(s, s0) - assert_same_columns_up_to_sign(vt.T, vt0.T) - - s = x.svd(compute_uv=False) - assert np.allclose(s, s0) - - # left _svd_gramian - u, s, vt = x.svd(complexity_bound=0) - assert_same_columns_up_to_sign(u, u0) - assert np.allclose(s, s0) - assert_same_columns_up_to_sign(vt.to_numpy().T, vt0.T) - - s = x.svd(compute_uv=False, complexity_bound=0) - assert np.allclose(s, s0) - - # right _svd_gramian - x = BlockMatrix.from_numpy(x0.T) - u, s, vt = x.svd(complexity_bound=0) - assert_same_columns_up_to_sign(u.to_numpy(), vt0.T) - assert np.allclose(s, s0) - assert_same_columns_up_to_sign(vt.T, u0) - - s = x.svd(compute_uv=False, complexity_bound=0) - assert np.allclose(s, s0) - - # left _svd_gramian when dimensions agree - x = BlockMatrix.from_numpy(x0[:, :2]) - u, s, vt = x.svd(complexity_bound=0) - assert isinstance(u, np.ndarray) - assert isinstance(vt, BlockMatrix) - - # rank-deficient X sets negative eigenvalues to 0.0 - a = np.array([[0.0, 1.0, np.e, np.pi, 10.0, 25.0]]) - x0 = a.T @ a # rank 1 - e, _ = np.linalg.eigh(x0 @ x0.T) - - x = BlockMatrix.from_numpy(x0) - s = x.svd(complexity_bound=0, compute_uv=False) - assert np.all(s >= 0.0) - - s = x.svd(compute_uv=False, complexity_bound=0) - assert np.all(s >= 0) - - def test_filtering(self): - np_square = np.arange(16, dtype=np.float64).reshape((4, 4)) - bm = BlockMatrix.from_numpy(np_square) - assert np.array_equal(bm.filter([3], [3]).to_numpy(), np.array([[15]])) - assert np.array_equal(bm.filter_rows([3]).filter_cols([3]).to_numpy(), np.array([[15]])) - assert np.array_equal(bm.filter_cols([3]).filter_rows([3]).to_numpy(), np.array([[15]])) - assert np.array_equal(bm.filter_rows([2]).filter_rows([0]).to_numpy(), np_square[2:3, :]) - assert np.array_equal(bm.filter_cols([2]).filter_cols([0]).to_numpy(), np_square[:, 2:3]) - - with pytest.raises(ValueError) as exc: - bm.filter_cols([0]).filter_cols([3]).to_numpy() - assert "index" in str(exc.value) - - with pytest.raises(ValueError) as exc: - bm.filter_rows([0]).filter_rows([3]).to_numpy() - assert "index" in str(exc.value) - - @fails_service_backend() - def test_is_sparse(self): - block_list = [1, 2] - np_square = np.arange(16, dtype=np.float64).reshape((4, 4)) - bm = BlockMatrix.from_numpy(np_square, block_size=2) - bm = bm._sparsify_blocks(block_list) - assert bm.is_sparse - assert np.array_equal( - bm.to_numpy(), - np.array([[0, 0, 2, 3], - [0, 0, 6, 7], - [8, 9, 0, 0], - [12, 13, 0, 0]])) - - def test_sparsify_blocks(self): - block_list = [1, 2] - np_square = np.arange(16, dtype=np.float64).reshape((4, 4)) - block_size = 2 - bm = BlockMatrix.from_numpy(np_square, block_size=block_size) - bm = bm._sparsify_blocks(block_list) - sparse_numpy = sparsify_numpy(np_square, block_size, block_list) - assert np.array_equal(bm.to_numpy(), sparse_numpy) - assert np.array_equal( - sparse_numpy, - np.array([[0, 0, 2, 3], - [0, 0, 6, 7], - [8, 9, 0, 0], - [12, 13, 0, 0]])) - - block_list = [4, 8, 10, 12, 13, 14] - np_square = np.arange(225, dtype=np.float64).reshape((15, 15)) - block_size = 4 - bm = BlockMatrix.from_numpy(np_square, block_size=block_size) - bm = bm._sparsify_blocks(block_list) - sparse_numpy = sparsify_numpy(np_square, block_size, block_list) - assert np.array_equal(bm.to_numpy(), sparse_numpy) - - def test_sparse_transposition(self): - block_list = [1, 2] - np_square = np.arange(16, dtype=np.float64).reshape((4, 4)) - block_size = 2 - bm = BlockMatrix.from_numpy(np_square, block_size=block_size) - sparse_bm = bm._sparsify_blocks(block_list).T - sparse_np = sparsify_numpy(np_square, block_size, block_list).T - assert np.array_equal(sparse_bm.to_numpy(), sparse_np) - - block_list = [4, 8, 10, 12, 13, 14] - np_square = np.arange(225, dtype=np.float64).reshape((15, 15)) - block_size = 4 - bm = BlockMatrix.from_numpy(np_square, block_size=block_size) - sparse_bm = bm._sparsify_blocks(block_list).T - sparse_np = sparsify_numpy(np_square, block_size, block_list).T - assert np.array_equal(sparse_bm.to_numpy(), sparse_np) - - block_list = [2, 5, 8, 10, 11] - np_square = np.arange(150, dtype=np.float64).reshape((10, 15)) - block_size = 4 - bm = BlockMatrix.from_numpy(np_square, block_size=block_size) - sparse_bm = bm._sparsify_blocks(block_list).T - sparse_np = sparsify_numpy(np_square, block_size, block_list).T - assert np.array_equal(sparse_bm.to_numpy(), sparse_np) - - block_list = [2, 5, 8, 10, 11] - np_square = np.arange(165, dtype=np.float64).reshape((15, 11)) - block_size = 4 - bm = BlockMatrix.from_numpy(np_square, block_size=block_size) - sparse_bm = bm._sparsify_blocks(block_list).T - sparse_np = sparsify_numpy(np_square, block_size, block_list).T - assert np.array_equal(sparse_bm.to_numpy(), sparse_np) - - def test_row_blockmatrix_sum(self): - - row = BlockMatrix.from_numpy(np.arange(10)) - col = row.T - - # Summing vertically along a column vector to get a single value - b = col.sum(axis=0) - assert b.to_numpy().shape == (1,1) - - # Summing horizontally along a row vector to create a single value - d = row.sum(axis=1) - assert d.to_numpy().shape == (1,1) - - # Summing vertically along a row vector to make sure nothing changes - e = row.sum(axis=0) - assert e.to_numpy().shape == (1, 10) - - # Summing horizontally along a column vector to make sure nothing changes - f = col.sum(axis=1) - assert f.to_numpy().shape == (10, 1) - - @fails_spark_backend() - def test_map(self): - np_mat = np.arange(20, dtype=np.float64).reshape((4, 5)) - bm = BlockMatrix.from_ndarray(hl.nd.array(np_mat)) - bm_mapped_arith = bm._map_dense(lambda x: (x * x) + 5) - self._assert_eq(bm_mapped_arith, np_mat * np_mat + 5) - - bm_mapped_if = bm._map_dense(lambda x: hl.if_else(x >= 1, x, -8.0)) - np_if = np_mat.copy() - np_if[0, 0] = -8.0 - self._assert_eq(bm_mapped_if, np_if) + + bm2 = BlockMatrix.from_numpy(np.array([[1]])) + bm2.write(path, overwrite=True) + _assert_eq(BlockMatrix.read(path), bm2) + + +def test_stage_locally(): + nd = np.arange(0, 80, dtype=float).reshape(8, 10) + with hl.TemporaryDirectory(ensure_exists=False) as bm_uri: + BlockMatrix.from_numpy(nd, block_size=3).write(bm_uri, stage_locally=True) + bm = BlockMatrix.read(bm_uri) + _assert_eq(nd, bm) + + +def test_svd(): + def assert_same_columns_up_to_sign(a, b): + for j in range(a.shape[1]): + assert np.allclose(a[:, j], b[:, j]) or np.allclose(-a[:, j], b[:, j]) + + x0 = np.array([[-2.0, 0.0, 3.0], + [-1.0, 2.0, 4.0]]) + u0, s0, vt0 = np.linalg.svd(x0, full_matrices=False) + + x = BlockMatrix.from_numpy(x0) + + # _svd + u, s, vt = x.svd() + assert_same_columns_up_to_sign(u, u0) + assert np.allclose(s, s0) + assert_same_columns_up_to_sign(vt.T, vt0.T) + + s = x.svd(compute_uv=False) + assert np.allclose(s, s0) + + # left _svd_gramian + u, s, vt = x.svd(complexity_bound=0) + assert_same_columns_up_to_sign(u, u0) + assert np.allclose(s, s0) + assert_same_columns_up_to_sign(vt.to_numpy().T, vt0.T) + + s = x.svd(compute_uv=False, complexity_bound=0) + assert np.allclose(s, s0) + + # right _svd_gramian + x = BlockMatrix.from_numpy(x0.T) + u, s, vt = x.svd(complexity_bound=0) + assert_same_columns_up_to_sign(u.to_numpy(), vt0.T) + assert np.allclose(s, s0) + assert_same_columns_up_to_sign(vt.T, u0) + + s = x.svd(compute_uv=False, complexity_bound=0) + assert np.allclose(s, s0) + + # left _svd_gramian when dimensions agree + x = BlockMatrix.from_numpy(x0[:, :2]) + u, s, vt = x.svd(complexity_bound=0) + assert isinstance(u, np.ndarray) + assert isinstance(vt, BlockMatrix) + + # rank-deficient X sets negative eigenvalues to 0.0 + a = np.array([[0.0, 1.0, np.e, np.pi, 10.0, 25.0]]) + x0 = a.T @ a # rank 1 + _, _ = np.linalg.eigh(x0 @ x0.T) + + x = BlockMatrix.from_numpy(x0) + s = x.svd(complexity_bound=0, compute_uv=False) + assert np.all(s >= 0.0) + + s = x.svd(compute_uv=False, complexity_bound=0) + assert np.all(s >= 0) + + +def test_filtering(): + np_square = np.arange(16, dtype=np.float64).reshape((4, 4)) + bm = BlockMatrix.from_numpy(np_square) + assert np.array_equal(bm.filter([3], [3]).to_numpy(), np.array([[15]])) + assert np.array_equal(bm.filter_rows([3]).filter_cols([3]).to_numpy(), np.array([[15]])) + assert np.array_equal(bm.filter_cols([3]).filter_rows([3]).to_numpy(), np.array([[15]])) + assert np.array_equal(bm.filter_rows([2]).filter_rows([0]).to_numpy(), np_square[2:3, :]) + assert np.array_equal(bm.filter_cols([2]).filter_cols([0]).to_numpy(), np_square[:, 2:3]) + + with pytest.raises(ValueError) as exc: + bm.filter_cols([0]).filter_cols([3]).to_numpy() + assert "index" in str(exc.value) + + with pytest.raises(ValueError) as exc: + bm.filter_rows([0]).filter_rows([3]).to_numpy() + assert "index" in str(exc.value) + + +@fails_service_backend() +def test_is_sparse(): + block_list = [1, 2] + np_square = np.arange(16, dtype=np.float64).reshape((4, 4)) + bm = BlockMatrix.from_numpy(np_square, block_size=2) + bm = bm._sparsify_blocks(block_list) + assert bm.is_sparse + assert np.array_equal( + bm.to_numpy(), + np.array([[0, 0, 2, 3], + [0, 0, 6, 7], + [8, 9, 0, 0], + [12, 13, 0, 0]])) + + +@pytest.mark.parametrize( + 'block_list,nrows,ncols,block_size', + [ ([1, 2], 4, 4, 2) + , ([4, 8, 10, 12, 13, 14], 15, 15, 4) + ] +) +def test_sparsify_blocks(block_list, nrows, ncols, block_size): + np_square = np.arange(nrows * ncols, dtype=np.float64).reshape((nrows, ncols)) + bm = BlockMatrix.from_numpy(np_square, block_size=block_size) + bm = bm._sparsify_blocks(block_list) + sparse_numpy = sparsify_numpy(np_square, block_size, block_list) + assert np.array_equal(bm.to_numpy(), sparse_numpy) + + +@pytest.mark.parametrize( + 'block_list,nrows,ncols,block_size', + [ ([1, 2], 4, 4, 2) + , ([4, 8, 10, 12, 13, 14], 15, 15, 4) + , ([2, 5, 8, 10, 11], 10, 15, 4) + , ([2, 5, 8, 10, 11], 15, 11, 4) + ] +) +def test_sparse_transposition(block_list, nrows, ncols, block_size): + np_square = np.arange(nrows * ncols, dtype=np.float64).reshape((nrows, ncols)) + bm = BlockMatrix.from_numpy(np_square, block_size=block_size) + sparse_bm = bm._sparsify_blocks(block_list).T + sparse_np = sparsify_numpy(np_square, block_size, block_list).T + assert np.array_equal(sparse_bm.to_numpy(), sparse_np) + + +def test_row_blockmatrix_sum(): + row = BlockMatrix.from_numpy(np.arange(10)) + col = row.T + + # Summing vertically along a column vector to get a single value + b = col.sum(axis=0) + assert b.to_numpy().shape == (1,1) + + # Summing horizontally along a row vector to create a single value + d = row.sum(axis=1) + assert d.to_numpy().shape == (1,1) + + # Summing vertically along a row vector to make sure nothing changes + e = row.sum(axis=0) + assert e.to_numpy().shape == (1, 10) + + # Summing horizontally along a column vector to make sure nothing changes + f = col.sum(axis=1) + assert f.to_numpy().shape == (10, 1) + + +@fails_spark_backend() +def test_map(): + np_mat = np.arange(20, dtype=np.float64).reshape((4, 5)) + bm = BlockMatrix.from_ndarray(hl.nd.array(np_mat)) + bm_mapped_arith = bm._map_dense(lambda x: (x * x) + 5) + _assert_eq(bm_mapped_arith, np_mat * np_mat + 5) + + bm_mapped_if = bm._map_dense(lambda x: hl.if_else(x >= 1, x, -8.0)) + np_if = np_mat.copy() + np_if[0, 0] = -8.0 + _assert_eq(bm_mapped_if, np_if) def test_from_entry_expr_simple_gt_n_alt_alleles(): From a31f94187545defa0a021dc10e2cef74c1e0c2a1 Mon Sep 17 00:00:00 2001 From: jigold Date: Fri, 4 Aug 2023 22:21:25 -0400 Subject: [PATCH 075/180] [azure] Optimize file status operations (#13368) I think this change will help the number of operations we're making substantially. My Scala skills are not great, so I don't know if this is written correctly. Basically, we were making a call to list the blobs recursively to test if the path was a directory which was streaming through the first 5000 records. I made the page size equal to 1 record as we don't care about all records. The next thing I did was to just get the blob properties rather than calling exists + get blob properties. So that will cut the number of HTTP calls by half for every blob. Lastly, listing items in a directory which is used for globbing was making a call to get the metadata for each file and then it was making the 3 API calls above to check whether it's a directory, whether it exists, and what the blob properties are. All of this information is in the original result from listing the blobs in the hierarchy so I just use that information directly. --- .../scala/is/hail/io/fs/AzureStorageFS.scala | 51 ++++++++++++------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala index 5f27a9d8774..60f3d587a24 100644 --- a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala @@ -2,7 +2,7 @@ package is.hail.io.fs import is.hail.shadedazure.com.azure.core.credential.{AzureSasCredential, TokenCredential} import is.hail.shadedazure.com.azure.identity.{ClientSecretCredential, ClientSecretCredentialBuilder, DefaultAzureCredential, DefaultAzureCredentialBuilder, ManagedIdentityCredentialBuilder} -import is.hail.shadedazure.com.azure.storage.blob.models.{BlobProperties, BlobRange, BlobStorageException, ListBlobsOptions} +import is.hail.shadedazure.com.azure.storage.blob.models.{BlobItem, BlobProperties, BlobRange, BlobStorageException, ListBlobsOptions} import is.hail.shadedazure.com.azure.storage.blob.specialized.BlockBlobClient import is.hail.shadedazure.com.azure.storage.blob.{BlobClient, BlobContainerClient, BlobServiceClient, BlobServiceClientBuilder} import is.hail.shadedazure.com.azure.core.http.HttpClient @@ -141,11 +141,21 @@ object AzureStorageFS { } object AzureStorageFileStatus { - def apply(blobProperties: BlobProperties, path: String, isDir: Boolean): BlobStorageFileStatus = { - val modificationTime = blobProperties.getLastModified.toEpochSecond - val size = blobProperties.getBlobSize + def apply(path: String, isDir: Boolean, blobProperties: BlobProperties): BlobStorageFileStatus = { + if (isDir) { + new BlobStorageFileStatus(path, null, 0, true) + } else { + new BlobStorageFileStatus(path, blobProperties.getLastModified.toEpochSecond, blobProperties.getBlobSize, false) + } + } - new BlobStorageFileStatus(path, modificationTime, size, isDir) + def apply(blobPath: String, blobItem: BlobItem): BlobStorageFileStatus = { + if (blobItem.isPrefix) { + new BlobStorageFileStatus(blobPath, null, 0, true) + } else { + val properties = blobItem.getProperties + new BlobStorageFileStatus(blobPath, properties.getLastModified.toEpochSecond, properties.getContentLength, false) + } } } @@ -389,8 +399,10 @@ class AzureStorageFS(val credentialsJSON: Option[String] = None) extends FS { val prefixMatches = blobContainerClient.listBlobsByHierarchy(prefix) prefixMatches.forEach(blobItem => { - statList += fileStatus(url.withPath(blobItem.getName)) + val blobPath = dropTrailingSlash(url.withPath(blobItem.getName).toString()) + statList += AzureStorageFileStatus(blobPath, blobItem) }) + statList.toArray } @@ -408,21 +420,26 @@ class AzureStorageFS(val credentialsJSON: Option[String] = None) extends FS { val blobContainerClient: BlobContainerClient = getContainerClient(url) val prefix = dropTrailingSlash(url.path) + "/" - val options: ListBlobsOptions = new ListBlobsOptions().setPrefix(prefix) - val prefixMatches = blobContainerClient.listBlobs(options, null) + val options: ListBlobsOptions = new ListBlobsOptions().setPrefix(prefix).setMaxResultsPerPage(1) + val prefixMatches = blobContainerClient.listBlobs(options, timeout) val isDir = prefixMatches.iterator().hasNext val filename = dropTrailingSlash(url.toString) - if (!isDir && !blobClient.exists()) { - throw new FileNotFoundException(s"File not found: $filename") - } - if (isDir) { - new BlobStorageFileStatus(path = filename, null, 0, isDir = true) - } else { - val blobProperties: BlobProperties = blobClient.getProperties - AzureStorageFileStatus(blobProperties, path = filename, isDir = false) - } + val blobProperties = if (!isDir) { + try { + blobClient.getProperties + } catch { + case e: BlobStorageException => + if (e.getStatusCode == 404) + throw new FileNotFoundException(s"File not found: $filename") + else + throw e + } + } else + null + + AzureStorageFileStatus(filename, isDir, blobProperties) } def fileStatus(filename: String): FileStatus = handlePublicAccessError(filename) { From 1c23b084cad8e2348f568a90a0479e21bdb3e90c Mon Sep 17 00:00:00 2001 From: Dan King Date: Sun, 6 Aug 2023 07:29:53 -0400 Subject: [PATCH 076/180] [k8s] more PDBs to allow scale down of non-preemptibles (#13384) --- infra/azure/modules/vdc/main.tf | 15 +++++++++++++++ infra/gcp-broad/main.tf | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/infra/azure/modules/vdc/main.tf b/infra/azure/modules/vdc/main.tf index 6b7e607dc45..16ee2e3bc4f 100644 --- a/infra/azure/modules/vdc/main.tf +++ b/infra/azure/modules/vdc/main.tf @@ -172,3 +172,18 @@ resource "kubernetes_pod_disruption_budget" "kube_dns_pdb" { } } } + +resource "kubernetes_pod_disruption_budget" "kube_dns_autoscaler_pdb" { + metadata { + name = "kube-dns-autoscaler" + namespace = "kube-system" + } + spec { + max_unavailable = "1" + selector { + match_labels = { + k8s-app = "kube-dns-autoscaler" + } + } + } +} diff --git a/infra/gcp-broad/main.tf b/infra/gcp-broad/main.tf index a527a8f0bb8..286addc6b68 100644 --- a/infra/gcp-broad/main.tf +++ b/infra/gcp-broad/main.tf @@ -860,6 +860,37 @@ resource "kubernetes_pod_disruption_budget" "kube_dns_pdb" { } } +resource "kubernetes_pod_disruption_budget" "kube_dns_autoscaler_pdb" { + metadata { + name = "kube-dns-autoscaler" + namespace = "kube-system" + } + spec { + max_unavailable = "1" + selector { + match_labels = { + k8s-app = "kube-dns-autoscaler" + } + } + } +} + +resource "kubernetes_pod_disruption_budget" "event_exporter_pdb" { + metadata { + name = "event-exporter" + namespace = "kube-system" + } + spec { + max_unavailable = "1" + selector { + match_labels = { + # nb: pods are called event-exporter-gke-... + k8s-app = "event-exporter" + } + } + } +} + data "sops_file" "ci_config_sops" { count = fileexists("${var.github_organization}/ci_config.enc.json") ? 1 : 0 source_file = "${var.github_organization}/ci_config.enc.json" From df17d7f88c0c8f041db5fb37494a18dcb2d492d4 Mon Sep 17 00:00:00 2001 From: Dan King Date: Mon, 7 Aug 2023 12:12:49 -0400 Subject: [PATCH 077/180] Upgrade to Python 3.9 (#13275) --- batch/Dockerfile.worker | 4 +- batch/batch/resources.py | 4 +- batch/batch/spec_writer.py | 3 +- batch/batch/worker/worker_api.py | 4 +- benchmark/Dockerfile | 4 +- benchmark/python/setup.py | 2 +- build.yaml | 88 ------------------- ci/bootstrap.py | 4 +- ci/ci/build.py | 7 +- ci/ci/ci.py | 8 +- dev-docs/compiler-team/development_tools.md | 4 +- dev-docs/development_process.md | 2 +- dev-docs/hail-for-new-engineers.md | 4 +- dev-docs/ksync.md | 2 +- docker/hail-ubuntu/Dockerfile | 4 +- docker/hailgenetics/mirror_images.sh | 2 - docker/hailgenetics/python-dill/push.sh | 2 +- docker/third-party/images.txt | 2 - generate_pip_lockfile.sh | 2 +- hail-pip-compile.sh | 2 +- hail/Dockerfile.hail-pip-installed-python38 | 16 ---- hail/Dockerfile.hail-pip-installed-python39 | 20 ----- hail/Dockerfile.hail-run | 2 +- hail/python/hail/__init__.py | 4 +- hail/python/hail/backend/spark_backend.py | 3 - hail/python/hail/docs/conf.py | 2 +- hail/python/hail/docs/install/linux.rst | 6 +- hail/python/hail/docs/install/macosx.rst | 2 +- .../hail/docs/install/other-cluster.rst | 2 +- hail/python/hail/utils/misc.py | 4 +- hail/python/hailtop/aiocloud/aioazure/fs.py | 2 +- hail/python/hailtop/aiotools/diff.py | 2 +- hail/python/hailtop/batch/backend.py | 11 +-- hail/python/hailtop/batch/batch.py | 4 +- .../hailtop/batch/batch_pool_executor.py | 18 +--- hail/python/hailtop/batch/docker.py | 6 +- hail/python/hailtop/batch/docs/conf.py | 2 +- .../batch/docs/cookbook/random_forest.rst | 2 +- .../hailtop/batch/docs/getting_started.rst | 2 +- .../hailtop/batch/hail_genetics_images.py | 13 +++ hail/python/hailtop/batch/job.py | 6 +- hail/python/hailtop/hailctl/auth/cli.py | 3 +- .../hailtop/hailctl/batch/batch_cli_utils.py | 4 +- hail/python/hailtop/hailctl/batch/cli.py | 3 +- hail/python/hailtop/hailctl/config/cli.py | 3 +- hail/python/hailtop/hailctl/dataproc/cli.py | 3 +- hail/python/hailtop/hailctl/describe.py | 3 +- hail/python/hailtop/hailctl/dev/cli.py | 3 +- hail/python/hailtop/hailctl/hdinsight/cli.py | 3 +- hail/python/hailtop/utils/utils.py | 2 +- hail/python/setup-hailtop.py | 2 +- hail/python/setup.py | 2 +- hail/python/test/hailtop/batch/test_batch.py | 2 +- .../hailtop/batch/test_batch_pool_executor.py | 2 +- .../inter_cloud/generate_copy_test_specs.py | 2 +- 55 files changed, 83 insertions(+), 237 deletions(-) delete mode 100644 hail/Dockerfile.hail-pip-installed-python38 delete mode 100644 hail/Dockerfile.hail-pip-installed-python39 diff --git a/batch/Dockerfile.worker b/batch/Dockerfile.worker index c5c27259b0a..561df7a409c 100644 --- a/batch/Dockerfile.worker +++ b/batch/Dockerfile.worker @@ -9,7 +9,7 @@ RUN hail-apt-get-install \ xfsprogs \ libyajl-dev -RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 +RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 {% if global.cloud == "gcp" %} RUN echo "APT::Acquire::Retries \"5\";" > /etc/apt/apt.conf.d/80-retries && \ @@ -40,7 +40,7 @@ RUN hail-pip-install \ -r batch-requirements.txt \ pyspark==3.3.0 -ENV SPARK_HOME /usr/local/lib/python3.8/dist-packages/pyspark +ENV SPARK_HOME /usr/local/lib/python3.9/dist-packages/pyspark ENV PATH "$PATH:$SPARK_HOME/sbin:$SPARK_HOME/bin" ENV PYSPARK_PYTHON python3 diff --git a/batch/batch/resources.py b/batch/batch/resources.py index e3af7999a26..d77589f0256 100644 --- a/batch/batch/resources.py +++ b/batch/batch/resources.py @@ -1,7 +1,5 @@ import abc -from typing import Any, Dict, Optional - -from typing_extensions import TypedDict +from typing import Any, Dict, Optional, TypedDict class QuantifiedResource(TypedDict): diff --git a/batch/batch/spec_writer.py b/batch/batch/spec_writer.py index 1c5427ada38..952e7e87f97 100644 --- a/batch/batch/spec_writer.py +++ b/batch/batch/spec_writer.py @@ -1,9 +1,8 @@ import collections import logging -from typing import Dict, Tuple +from typing import Dict, Literal, Tuple import sortedcontainers -from typing_extensions import Literal from hailtop.utils import secret_alnum_string diff --git a/batch/batch/worker/worker_api.py b/batch/batch/worker/worker_api.py index 238469f35af..8bc2f9d3ea9 100644 --- a/batch/batch/worker/worker_api.py +++ b/batch/batch/worker/worker_api.py @@ -1,7 +1,5 @@ import abc -from typing import Dict, Generic, TypeVar - -from typing_extensions import TypedDict +from typing import Dict, Generic, TypedDict, TypeVar from hailtop import httpx from hailtop.aiotools.fs import AsyncFS diff --git a/benchmark/Dockerfile b/benchmark/Dockerfile index 632ef4185b5..720ff9dc0d7 100644 --- a/benchmark/Dockerfile +++ b/benchmark/Dockerfile @@ -15,9 +15,9 @@ RUN apt-get update && \ xsltproc pandoc \ jq \ python \ - python3.8 python3-pip python3.8-dev \ + python3.9 python3-pip python3.9-dev \ liblapack3 && \ - update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 && \ + update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 && \ rm -rf /var/lib/apt/lists/* RUN wget -O - https://packages.adoptium.net/artifactory/api/gpg/key/public | apt-key add - && \ diff --git a/benchmark/python/setup.py b/benchmark/python/setup.py index 4b2f9c876e6..b348f5d67ad 100755 --- a/benchmark/python/setup.py +++ b/benchmark/python/setup.py @@ -16,7 +16,7 @@ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", ], - python_requires=">=3.8", + python_requires=">=3.9", install_requires=[ 'hail>=0.2', ], diff --git a/build.yaml b/build.yaml index 9211c73b8ac..a7553b64797 100644 --- a/build.yaml +++ b/build.yaml @@ -943,94 +943,6 @@ steps: - create_test_gsa_keys - build_hail_debug_jar_and_wheel - build_hail_test_artifacts - - kind: buildImage2 - name: hail_pip_installed_python39_image - dockerFile: /io/repo/hail/Dockerfile.hail-pip-installed-python39 - contextPath: /io/repo - publishAs: hail-pip-installed-python39 - inputs: - - from: /repo/hail/Dockerfile.hail-pip-installed-python39 - to: /io/repo/hail/Dockerfile.hail-pip-installed-python39 - - from: /repo/hail/python/pinned-requirements.txt - to: /io/repo/hail/python/pinned-requirements.txt - - from: /repo/hail/python/dev/pinned-requirements.txt - to: /io/repo/hail/python/dev/pinned-requirements.txt - - from: /repo/pylintrc - to: /io/repo/pylintrc - - from: /repo/setup.cfg - to: /io/repo/setup.cfg - - from: /repo/pyproject.toml - to: /io/repo/pyproject.toml - - from: /wheel-container.tar - to: /io/repo/wheel-container.tar - dependsOn: - - build_hail_jar_and_wheel - - hail_ubuntu_image - - merge_code - - kind: buildImage2 - name: hail_pip_installed_python38_image - dockerFile: /io/repo/hail/Dockerfile.hail-pip-installed-python38 - contextPath: /io/repo - publishAs: hail-pip-installed-python38 - inputs: - - from: /repo/hail/Dockerfile.hail-pip-installed-python38 - to: /io/repo/hail/Dockerfile.hail-pip-installed-python38 - - from: /repo/hail/python/pinned-requirements.txt - to: /io/repo/hail/python/pinned-requirements.txt - - from: /repo/hail/python/dev/pinned-requirements.txt - to: /io/repo/hail/python/dev/pinned-requirements.txt - - from: /repo/pylintrc - to: /io/repo/pylintrc - - from: /repo/setup.cfg - to: /io/repo/setup.cfg - - from: /repo/pyproject.toml - to: /io/repo/pyproject.toml - - from: /wheel-container.tar - to: /io/repo/wheel-container.tar - dependsOn: - - build_hail_jar_and_wheel - - hail_ubuntu_image - - merge_code - - kind: runImage - name: check_hail_python39 - image: - valueFrom: hail_pip_installed_python39_image.image - script: | - set -x - SITE_PACKAGES=$(pip3 show hail | grep Location | sed 's/Location: //') - - exit_status=0 - - ruff check --config pyproject.toml --ignore I --ignore PL --ignore RUF $SITE_PACKAGES/hail || exit_status=$? - ruff check --config pyproject.toml --ignore I $SITE_PACKAGES/hailtop || exit_status=$? - python3 -m pylint --rcfile pylintrc hailtop || exit_status=$? - # working around this: https://github.com/python/mypy/issues/7087 - ln -s $SITE_PACKAGES/hailtop hailtop - mypy --config-file /setup.cfg -p hailtop || exit_status=$? - - exit $exit_status - dependsOn: - - hail_pip_installed_python39_image - - kind: runImage - name: check_hail_python38 - image: - valueFrom: hail_pip_installed_python38_image.image - script: | - set -x - SITE_PACKAGES=$(pip3 show hail | grep Location | sed 's/Location: //') - - exit_status=0 - - ruff check --config pyproject.toml --ignore I --ignore PL --ignore RUF $SITE_PACKAGES/hail || exit_status=$? - ruff check --config pyproject.toml --ignore I $SITE_PACKAGES/hailtop || exit_status=$? - python3 -m pylint --rcfile pylintrc hailtop || exit_status=$? - # working around this: https://github.com/python/mypy/issues/7087 - ln -s $SITE_PACKAGES/hailtop hailtop - mypy --config-file /setup.cfg -p hailtop || exit_status=$? - - exit $exit_status - dependsOn: - - hail_pip_installed_python38_image - kind: buildImage2 name: notebook_image dockerFile: /io/repo/notebook/Dockerfile diff --git a/ci/bootstrap.py b/ci/bootstrap.py index 839dec64fd2..babd4602bba 100644 --- a/ci/bootstrap.py +++ b/ci/bootstrap.py @@ -133,7 +133,7 @@ async def run(self): assert src.startswith(prefix), (prefix, src) files.append( { - 'from': f'/shared{src[len(prefix):]}', + 'from': f'/shared{src.removeprefix(prefix)}', 'to': dest, } ) @@ -270,7 +270,7 @@ async def run(self): files.append( { 'from': src, - 'to': f'/shared{dest[len(prefix):]}', + 'to': f'/shared{dest.removeprefix(prefix)}', } ) output_cid, output_ok = await docker_run( diff --git a/ci/ci/build.py b/ci/ci/build.py index baa77e36802..d0a67ad5f15 100644 --- a/ci/ci/build.py +++ b/ci/ci/build.py @@ -3,11 +3,10 @@ import logging from collections import Counter, defaultdict from shlex import quote as shq -from typing import Dict, List, Optional +from typing import Dict, List, Optional, TypedDict import jinja2 import yaml -from typing_extensions import TypedDict from gear.cloud_config import get_global_config from hailtop.utils import RETRY_FUNCTION_SCRIPT, flatten @@ -415,8 +414,8 @@ def cleanup(self, batch, scope, parents): if CLOUD == 'azure': image = 'mcr.microsoft.com/azure-cli' - assert self.image.startswith(DOCKER_PREFIX) - image_name = self.image[len(f'{DOCKER_PREFIX}/') :] + assert self.image.startswith(DOCKER_PREFIX + '/') + image_name = self.image.removeprefix(DOCKER_PREFIX + '/') script = f''' set -x date diff --git a/ci/ci/ci.py b/ci/ci/ci.py index 13fb6fdf2bf..a3fa29fcb31 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -4,7 +4,7 @@ import logging import os import traceback -from typing import Callable, Dict, List, Optional, Set, Tuple +from typing import Callable, Dict, List, Optional, Set, Tuple, TypedDict import aiohttp_session # type: ignore import kubernetes_asyncio @@ -17,7 +17,6 @@ from gidgethub import routing as gh_routing from gidgethub import sansio as gh_sansio from prometheus_async.aio.web import server_stats # type: ignore -from typing_extensions import TypedDict from gear import ( AuthClient, @@ -199,8 +198,7 @@ async def get_pr(request: web.Request, userdata: UserData) -> web.Response: def storage_uri_to_url(uri: str) -> str: if uri.startswith('gs://'): - protocol = 'gs://' - path = uri[len(protocol) :] + path = uri.removeprefix('gs://') return f'https://console.cloud.google.com/storage/browser/{path}' return uri @@ -381,7 +379,7 @@ async def push_callback(event): data = event.data ref = data['ref'] if ref.startswith('refs/heads/'): - branch_name = ref[len('refs/heads/') :] + branch_name = ref.removeprefix('refs/heads/') branch = FQBranch(Repo.from_gh_json(data['repository']), branch_name) for wb in watched_branches: if wb.branch == branch: diff --git a/dev-docs/compiler-team/development_tools.md b/dev-docs/compiler-team/development_tools.md index 1829031402d..e1eb013ca78 100644 --- a/dev-docs/compiler-team/development_tools.md +++ b/dev-docs/compiler-team/development_tools.md @@ -51,7 +51,7 @@ https://www.anaconda.com/download/#macos After installing Anaconda, you should create a new dev environment for Hail with: - conda create --name hail python=3.8 + conda create --name hail python=3.9 and @@ -76,4 +76,4 @@ https://iterm2.com/ We primarily use Google Cloud for development. Get the SDK here: -https://cloud.google.com/sdk/docs/install \ No newline at end of file +https://cloud.google.com/sdk/docs/install diff --git a/dev-docs/development_process.md b/dev-docs/development_process.md index 046d8646a7a..e845f9dfdb7 100644 --- a/dev-docs/development_process.md +++ b/dev-docs/development_process.md @@ -27,7 +27,7 @@ feature into smaller components. Before you can write code, there are some setup steps that will allow you to develop effectively. -Hail currently supports Python version 3.8 or greater. +Hail currently supports Python version 3.9 or greater. ``` make install-dev-requirements diff --git a/dev-docs/hail-for-new-engineers.md b/dev-docs/hail-for-new-engineers.md index 27be9ef69b6..ee5b6b12585 100644 --- a/dev-docs/hail-for-new-engineers.md +++ b/dev-docs/hail-for-new-engineers.md @@ -154,8 +154,8 @@ We use a number of technologies: ### Services Technology -We almost exclusively write services in Python 3.8. We use a number of Python packages: -- [`asyncio`](https://docs.python.org/3.8/library/asyncio.html) for concurrency which is built on +We almost exclusively write services in Python 3.9. We use a number of Python packages: +- [`asyncio`](https://docs.python.org/3.9/library/asyncio.html) for concurrency which is built on [coroutines](https://en.wikipedia.org/wiki/Coroutine) not threads - [`aiohttp`](https://docs.aiohttp.org/en/stable/) for serving HTTPS requests (most services speak HTTPS) diff --git a/dev-docs/ksync.md b/dev-docs/ksync.md index 55e1e3e8e3a..9cfcda478be 100644 --- a/dev-docs/ksync.md +++ b/dev-docs/ksync.md @@ -79,7 +79,7 @@ ksync watch 3. Create a spec in ~/.ksync/ksync.yaml using the create operation ``` -ksync create --local-read-only -l app=auth --name - -n jigold $(pwd)// /usr/local/lib/python3.8/dist-packages// +ksync create --local-read-only -l app=auth --name - -n jigold $(pwd)// /usr/local/lib/python3.9/dist-packages// ``` 4. Use ksync get to make sure the pods are being watched diff --git a/docker/hail-ubuntu/Dockerfile b/docker/hail-ubuntu/Dockerfile index 632fdcec935..fd5abeed626 100644 --- a/docker/hail-ubuntu/Dockerfile +++ b/docker/hail-ubuntu/Dockerfile @@ -20,8 +20,8 @@ RUN chmod 755 /bin/retry && \ >> /etc/apt/sources.list && \ echo 'deb-src [signed-by=/usr/share/keyrings/deadsnakes-ppa-archive-keyring.gpg] http://ppa.launchpad.net/deadsnakes/ppa/ubuntu focal main' \ >> /etc/apt/sources.list && \ - hail-apt-get-install python3.8-minimal python3.8-dev python3.8-distutils gcc g++ && \ - update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 && \ + hail-apt-get-install python3.9-minimal python3.9-dev python3.9-distutils gcc g++ && \ + update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 && \ curl https://bootstrap.pypa.io/get-pip.py | python3 && \ python3 -m pip install 'pip>=21<22' && \ python3 -m pip check && \ diff --git a/docker/hailgenetics/mirror_images.sh b/docker/hailgenetics/mirror_images.sh index d3765ca91b8..dae12226d4e 100755 --- a/docker/hailgenetics/mirror_images.sh +++ b/docker/hailgenetics/mirror_images.sh @@ -32,8 +32,6 @@ then fi images=( - "python-dill:3.8" - "python-dill:3.8-slim" "python-dill:3.9" "python-dill:3.9-slim" "python-dill:3.10" diff --git a/docker/hailgenetics/python-dill/push.sh b/docker/hailgenetics/python-dill/push.sh index c2b4dec98de..f9697028a9c 100644 --- a/docker/hailgenetics/python-dill/push.sh +++ b/docker/hailgenetics/python-dill/push.sh @@ -2,7 +2,7 @@ cd $(dirname $0) set -ex -for version in 3.8 3.8-slim 3.9 3.9-slim 3.10 3.10-slim 3.11 3.11-slim +for version in 3.9 3.9-slim 3.10 3.10-slim 3.11 3.11-slim do public=hailgenetics/python-dill:$version diff --git a/docker/third-party/images.txt b/docker/third-party/images.txt index 0a9549f3673..fab1ad7f6c7 100644 --- a/docker/third-party/images.txt +++ b/docker/third-party/images.txt @@ -7,8 +7,6 @@ grafana/grafana:9.1.4 jupyter/scipy-notebook jupyter/scipy-notebook:c094bb7219f9 moby/buildkit:v0.8.3-rootless -python:3.8 -python:3.8-slim python:3.9 python:3.9-slim python:3.10 diff --git a/generate_pip_lockfile.sh b/generate_pip_lockfile.sh index 945cca198f7..5f96fa0383f 100755 --- a/generate_pip_lockfile.sh +++ b/generate_pip_lockfile.sh @@ -15,6 +15,6 @@ if [[ "$(uname)" == 'Linux' ]]; then else docker run --rm -it \ -v ${HAIL_HAIL_DIR}:/hail \ - python:3.8-slim \ + python:3.9-slim \ /bin/bash -c "pip install 'pip-tools==6.13.0' && cd /hail && pip-compile --upgrade $reqs --output-file=$pinned_reqs" fi diff --git a/hail-pip-compile.sh b/hail-pip-compile.sh index 1a2c8ceece1..2da605d41cf 100644 --- a/hail-pip-compile.sh +++ b/hail-pip-compile.sh @@ -9,7 +9,7 @@ PIP_COMPILE_IMAGE=hail-pip-compile:latest if [[ "$(docker images -q $PIP_COMPILE_IMAGE 2>/dev/null)" == "" ]]; then docker build -t $PIP_COMPILE_IMAGE -f - . < $file && \ - hail-pip-install -r $file - -RUN --mount=src=wheel-container.tar,target=/wheel-container.tar \ - tar -xf wheel-container.tar && \ - hail-pip-install --no-deps hail-*-py3-none-any.whl - -COPY pylintrc setup.cfg pyproject.toml / diff --git a/hail/Dockerfile.hail-pip-installed-python39 b/hail/Dockerfile.hail-pip-installed-python39 deleted file mode 100644 index ecf9fd2c030..00000000000 --- a/hail/Dockerfile.hail-pip-installed-python39 +++ /dev/null @@ -1,20 +0,0 @@ -FROM {{ hail_ubuntu_image.image }} - -ENV LANG C.UTF-8 - -RUN hail-apt-get-install \ - openjdk-8-jdk-headless \ - python3.9 \ - && update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 - -COPY hail/python/pinned-requirements.txt requirements.txt -COPY hail/python/dev/pinned-requirements.txt dev-requirements.txt -RUN file=$(mktemp) && \ - cat requirements.txt dev-requirements.txt > $file && \ - hail-pip-install -r $file - -RUN --mount=src=wheel-container.tar,target=/wheel-container.tar \ - tar -xf wheel-container.tar && \ - hail-pip-install --no-deps hail-*-py3-none-any.whl - -COPY pylintrc setup.cfg pyproject.toml / diff --git a/hail/Dockerfile.hail-run b/hail/Dockerfile.hail-run index 58024817ee4..09998b6374d 100644 --- a/hail/Dockerfile.hail-run +++ b/hail/Dockerfile.hail-run @@ -12,7 +12,7 @@ COPY hail/python/pinned-requirements.txt requirements.txt COPY hail/python/dev/pinned-requirements.txt dev-requirements.txt RUN hail-pip-install -r requirements.txt -r dev-requirements.txt -ENV SPARK_HOME /usr/local/lib/python3.8/dist-packages/pyspark +ENV SPARK_HOME /usr/local/lib/python3.9/dist-packages/pyspark ENV PATH "$PATH:$SPARK_HOME/sbin:$SPARK_HOME/bin" ENV PYSPARK_PYTHON python3 ENV PYSPARK_SUBMIT_ARGS "--conf spark.kryo.registrator=is.hail.kryo.HailKryoRegistrator pyspark-shell" diff --git a/hail/python/hail/__init__.py b/hail/python/hail/__init__.py index 6aaa4d26272..7f0d61f156b 100644 --- a/hail/python/hail/__init__.py +++ b/hail/python/hail/__init__.py @@ -2,8 +2,8 @@ import pkg_resources import sys -if sys.version_info < (3, 6): - raise EnvironmentError('Hail requires Python 3.6 or later, found {}.{}'.format( +if sys.version_info < (3, 9): + raise EnvironmentError('Hail requires Python 3.9 or later, found {}.{}'.format( sys.version_info.major, sys.version_info.minor)) diff --git a/hail/python/hail/backend/spark_backend.py b/hail/python/hail/backend/spark_backend.py index c3e959cb314..7a1e063d13a 100644 --- a/hail/python/hail/backend/spark_backend.py +++ b/hail/python/hail/backend/spark_backend.py @@ -22,9 +22,6 @@ from .py4j_backend import Py4JBackend, handle_java_exception from ..hail_logging import Logger -if pyspark.__version__ < '3' and sys.version_info > (3, 8): - raise EnvironmentError('Hail with spark {} requires Python 3.7, found {}.{}'.format( - pyspark.__version__, sys.version_info.major, sys.version_info.minor)) _installed = False _original = None diff --git a/hail/python/hail/docs/conf.py b/hail/python/hail/docs/conf.py index fb181596164..4bc6858c43d 100644 --- a/hail/python/hail/docs/conf.py +++ b/hail/python/hail/docs/conf.py @@ -69,7 +69,7 @@ napoleon_use_param = False intersphinx_mapping = { - 'python': ('https://docs.python.org/3.8', None), + 'python': ('https://docs.python.org/3.9', None), 'PySpark': ('https://spark.apache.org/docs/latest/api/python/', None), 'Bokeh': ('https://docs.bokeh.org/en/3.1.0/', None), 'numpy': ('https://numpy.org/doc/stable/', None), diff --git a/hail/python/hail/docs/install/linux.rst b/hail/python/hail/docs/install/linux.rst index 42221207edb..69daca4f5b7 100644 --- a/hail/python/hail/docs/install/linux.rst +++ b/hail/python/hail/docs/install/linux.rst @@ -3,7 +3,7 @@ Install Hail on GNU/Linux ========================= - Install Java 8 or Java 11. -- Install Python 3.8 or later. +- Install Python 3.9 or later. - Install a recent version of the C and C++ standard libraries. GCC 5.0, LLVM version 3.4, or any later versions suffice. - Install BLAS and LAPACK. @@ -16,8 +16,8 @@ On a recent Debian-like system, the following should suffice: apt-get install -y \ openjdk-8-jre-headless \ g++ \ - python3.8 python3-pip \ + python3.9 python3-pip \ libopenblas-base liblapack3 - python3.8 -m pip install hail + python3.9 -m pip install hail `Now let's take Hail for a spin! `__ diff --git a/hail/python/hail/docs/install/macosx.rst b/hail/python/hail/docs/install/macosx.rst index b3e4752642c..5eb3f009e6b 100644 --- a/hail/python/hail/docs/install/macosx.rst +++ b/hail/python/hail/docs/install/macosx.rst @@ -11,6 +11,6 @@ Install Hail on Mac OS X brew tap homebrew/cask-versions brew install --cask temurin8 -- Install Python 3.8 or later. We recommend `Miniconda `__. +- Install Python 3.9 or later. We recommend `Miniconda `__. - Open Terminal.app and execute ``pip install hail``. If this command fails with a message about "Rust", please try this instead: ``pip install hail --only-binary=:all:``. - `Run your first Hail query! `__ diff --git a/hail/python/hail/docs/install/other-cluster.rst b/hail/python/hail/docs/install/other-cluster.rst index 821f5610a52..428046c6fbe 100644 --- a/hail/python/hail/docs/install/other-cluster.rst +++ b/hail/python/hail/docs/install/other-cluster.rst @@ -11,7 +11,7 @@ Hail needs to be built from source on the leader node. Building Hail from source requires: - Java 8 or 11 JDK. -- Python 3.8 or later. +- Python 3.9 or later. - A recent C and a C++ compiler, GCC 5.0, LLVM 3.4, or later versions of either suffice. - The LZ4 library. diff --git a/hail/python/hail/utils/misc.py b/hail/python/hail/utils/misc.py index 8ab258c79ce..a2630e277f2 100644 --- a/hail/python/hail/utils/misc.py +++ b/hail/python/hail/utils/misc.py @@ -11,11 +11,9 @@ from collections import defaultdict, Counter from contextlib import contextmanager from io import StringIO -from typing import Optional +from typing import Optional, Literal from urllib.parse import urlparse -from typing_extensions import Literal - import hail import hail as hl from hail.typecheck import enumeration, typecheck, nullable diff --git a/hail/python/hailtop/aiocloud/aioazure/fs.py b/hail/python/hailtop/aiocloud/aioazure/fs.py index 868d03379da..2f4eb9ea8b9 100644 --- a/hail/python/hailtop/aiocloud/aioazure/fs.py +++ b/hail/python/hailtop/aiocloud/aioazure/fs.py @@ -371,7 +371,7 @@ def __init__(self, *, credential_file: Optional[str] = None, credentials: Option @staticmethod def valid_url(url: str) -> bool: if url.startswith('https://'): - stripped_scheme = url[len('https://'):] + stripped_scheme = url.removeprefix('https://') authority = stripped_scheme.split('/', maxsplit=1)[0] if '.' not in authority: return False diff --git a/hail/python/hailtop/aiotools/diff.py b/hail/python/hailtop/aiotools/diff.py index eadcafb71a3..1e9e2678aca 100644 --- a/hail/python/hailtop/aiotools/diff.py +++ b/hail/python/hailtop/aiotools/diff.py @@ -93,7 +93,7 @@ async def create_work(): async for source_status in filegenerator: source_url = await source_status.url() assert source_url.startswith(top_source) - suffix = source_url[len(top_source):] + suffix = source_url.removeprefix(top_source) target_url = top_target + suffix pbar.update(0, total=pbar.total() + 1) diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index 371f8129e67..175aea1eb2c 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -1,5 +1,4 @@ from typing import Optional, Dict, Any, TypeVar, Generic, List, Union, ClassVar -import sys import abc import asyncio import collections @@ -19,7 +18,8 @@ from hailtop.config import configuration_of, get_deploy_config, get_remote_tmpdir from hailtop.utils.rich_progress_bar import SimpleRichProgressBar from hailtop.utils import parse_docker_image_reference, async_to_blocking, bounded_gather, url_scheme -from hailtop.batch.hail_genetics_images import HAIL_GENETICS_IMAGES +from hailtop.batch.hail_genetics_images import HAIL_GENETICS_IMAGES, hailgenetics_python_dill_image_for_current_python_version + from hailtop.batch_client.parse import parse_cpu_in_mcpu import hailtop.batch_client.client as bc from hailtop.batch_client.client import BatchClient @@ -648,12 +648,7 @@ def symlink_input_resource_group(r): pyjobs = [j for j in unsubmitted_jobs if isinstance(j, _job.PythonJob)] for pyjob in pyjobs: if pyjob._image is None: - version = sys.version_info - if version.major != 3 or version.minor not in (8, 9, 10, 11): - raise BatchException( - f"You must specify 'image' for Python jobs if you are using a Python version other than 3.8, 3.9, 3.10, or 3.11 (you are using {version})") - pyjob._image = f'hailgenetics/python-dill:{version.major}.{version.minor}-slim' - + pyjob._image = hailgenetics_python_dill_image_for_current_python_version() await batch._serialize_python_functions_to_input_files( batch_remote_tmpdir, dry_run=dry_run ) diff --git a/hail/python/hailtop/batch/batch.py b/hail/python/hailtop/batch/batch.py index 3d7bc9b98fd..38f11b165d2 100644 --- a/hail/python/hailtop/batch/batch.py +++ b/hail/python/hailtop/batch/batch.py @@ -85,7 +85,7 @@ class Batch: any repository prefix and tags if desired (default tag is `latest`). The image must have the `dill` Python package installed and have the same version of Python installed that is currently running. If `None`, a compatible Python image with `dill` pre-installed will - automatically be used if the current Python version is 3.8, 3.9, or 3.10. + automatically be used if the current Python version is 3.9, or 3.10. project: DEPRECATED: please specify `google_project` on the ServiceBackend instead. If specified, the project to use when authenticating with Google Storage. Google Storage is used to @@ -331,7 +331,7 @@ def new_python_job(self, .. code-block:: python - b = Batch(default_python_image='hailgenetics/python-dill:3.8-slim') + b = Batch(default_python_image='hailgenetics/python-dill:3.9-slim') def hello(name): return f'hello {name}' diff --git a/hail/python/hailtop/batch/batch_pool_executor.py b/hail/python/hailtop/batch/batch_pool_executor.py index 92cdb05b228..77f0aabf366 100644 --- a/hail/python/hailtop/batch/batch_pool_executor.py +++ b/hail/python/hailtop/batch/batch_pool_executor.py @@ -6,9 +6,9 @@ import concurrent import dill import functools -import sys from hailtop.utils import secret_alnum_string, partition +from hailtop.batch.hail_genetics_images import hailgenetics_python_dill_image_for_current_python_version import hailtop.batch_client.aioclient as low_level_batch_client from hailtop.batch_client.parse import parse_cpu_in_mcpu from hailtop.aiotools.router_fs import RouterAsyncFS @@ -17,14 +17,6 @@ from .backend import ServiceBackend -if sys.version_info < (3, 7): - def create_task(coro, *, name=None): # pylint: disable=unused-argument - return asyncio.ensure_future(coro) -else: - def create_task(*args, **kwargs): - return asyncio.create_task(*args, **kwargs) # pylint: disable=no-member - - def cpu_spec_to_float(spec: Union[int, str]) -> float: if isinstance(spec, str): mcpu = parse_cpu_in_mcpu(spec) @@ -94,7 +86,7 @@ class BatchPoolExecutor: Backend used to execute the jobs. Must be a :class:`.ServiceBackend`. image: The name of a Docker image used for each submitted job. The image must - include Python 3.8 or later and must have the ``dill`` Python package + include Python 3.9 or later and must have the ``dill`` Python package installed. If you intend to use ``numpy``, ensure that OpenBLAS is also installed. If unspecified, an image with a matching Python verison and ``numpy``, ``scipy``, and ``sklearn`` installed is used. @@ -143,12 +135,8 @@ def __init__(self, *, self.futures: List[BatchPoolFuture] = [] self.finished_future_count = 0 self._shutdown = False - version = sys.version_info if image is None: - if version.major != 3 or version.minor not in (8, 9, 10): - raise ValueError( - f'You must specify an image if you are using a Python version other than 3.8, 3.9 or 3.10 (you are using {version})') - self.image = f'hailgenetics/python-dill:{version.major}.{version.minor}-slim' + self.image = hailgenetics_python_dill_image_for_current_python_version() else: self.image = image self.cpus_per_job = cpus_per_job diff --git a/hail/python/hailtop/batch/docker.py b/hail/python/hailtop/batch/docker.py index d5111609cf9..2333a99cde5 100644 --- a/hail/python/hailtop/batch/docker.py +++ b/hail/python/hailtop/batch/docker.py @@ -34,7 +34,7 @@ def build_python_image(fullname: str, requirements: List of pip packages to install. python_version: - String in the format of `major_version.minor_version` (ex: `3.8`). Defaults to + String in the format of `major_version.minor_version` (ex: `3.9`). Defaults to current version of Python that is running. _tmp_dir: Location to place local temporary files used while building the image. @@ -54,9 +54,9 @@ def build_python_image(fullname: str, major_version = int(version[0]) minor_version = int(version[1]) - if major_version != 3 or minor_version < 8: + if major_version != 3 or minor_version < 9: raise ValueError( - f'Python versions older than 3.8 (you are using {major_version}.{minor_version}) are not supported') + f'Python versions older than 3.9 (you are using {major_version}.{minor_version}) are not supported') base_image = f'hailgenetics/python-dill:{major_version}.{minor_version}-slim' diff --git a/hail/python/hailtop/batch/docs/conf.py b/hail/python/hailtop/batch/docs/conf.py index 258ce5834b5..b5d4d94436f 100644 --- a/hail/python/hailtop/batch/docs/conf.py +++ b/hail/python/hailtop/batch/docs/conf.py @@ -118,7 +118,7 @@ # html_sidebars = {} # https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html -intersphinx_mapping = {'python': ('https://docs.python.org/3.8', None)} +intersphinx_mapping = {'python': ('https://docs.python.org/3.9', None)} # -- Extension configuration ------------------------------------------------- diff --git a/hail/python/hailtop/batch/docs/cookbook/random_forest.rst b/hail/python/hailtop/batch/docs/cookbook/random_forest.rst index badc7e80775..a3ebe6de60b 100644 --- a/hail/python/hailtop/batch/docs/cookbook/random_forest.rst +++ b/hail/python/hailtop/batch/docs/cookbook/random_forest.rst @@ -120,7 +120,7 @@ Build Python Image In order to run a :class:`.PythonJob`, Batch needs an image that has the same version of Python as the version of Python running on your computer and the Python package `dill` installed. Batch will automatically -choose a suitable image for you if your Python version is 3.8 or newer. +choose a suitable image for you if your Python version is 3.9 or newer. You can supply your own image that meets the requirements listed above to the method :meth:`.PythonJob.image` or as the argument `default_python_image` when constructing a Batch . We also provide a convenience function :func:`.docker.build_python_image` diff --git a/hail/python/hailtop/batch/docs/getting_started.rst b/hail/python/hailtop/batch/docs/getting_started.rst index 4f76a5b64e1..2e385c99412 100644 --- a/hail/python/hailtop/batch/docs/getting_started.rst +++ b/hail/python/hailtop/batch/docs/getting_started.rst @@ -20,7 +20,7 @@ Create a `conda enviroment .. code-block:: sh - conda create -n hail python'>=3.8' + conda create -n hail python'>=3.9' conda activate hail pip install hail diff --git a/hail/python/hailtop/batch/hail_genetics_images.py b/hail/python/hailtop/batch/hail_genetics_images.py index f6bdf33f97a..d90497a92c5 100644 --- a/hail/python/hailtop/batch/hail_genetics_images.py +++ b/hail/python/hailtop/batch/hail_genetics_images.py @@ -1,4 +1,17 @@ +import sys + + HAIL_GENETICS = 'hailgenetics/' HAIL_GENETICS_IMAGES = [ HAIL_GENETICS + name for name in ('hail', 'hailtop', 'genetics', 'python-dill', 'vep-grch37-85', 'vep-grch38-95')] + + +def hailgenetics_python_dill_image_for_current_python_version(): + version = sys.version_info + if version.major != 3 or version.minor not in (9, 10, 11): + raise ValueError( + f'You must specify an "image" for Python jobs and the BatchPoolExecutor if you are ' + f'using a Python version other than 3.9, 3.10, or 3.11 (you are using {version})' + ) + return f'hailgenetics/python-dill:{version.major}.{version.minor}-slim' diff --git a/hail/python/hailtop/batch/job.py b/hail/python/hailtop/batch/job.py index 942dae76589..c6e8b1d7d3b 100644 --- a/hail/python/hailtop/batch/job.py +++ b/hail/python/hailtop/batch/job.py @@ -864,7 +864,7 @@ class PythonJob(Job): # Create a batch object with a default Python image - b = Batch(default_python_image='hailgenetics/python-dill:3.8-slim') + b = Batch(default_python_image='hailgenetics/python-dill:3.9-slim') def multiply(x, y): return x * y @@ -922,11 +922,11 @@ def image(self, image: str) -> 'PythonJob': Examples -------- - Set the job's docker image to `hailgenetics/python-dill:3.8-slim`: + Set the job's docker image to `hailgenetics/python-dill:3.9-slim`: >>> b = Batch() >>> j = b.new_python_job() - >>> (j.image('hailgenetics/python-dill:3.8-slim') + >>> (j.image('hailgenetics/python-dill:3.9-slim') ... .call(print, 'hello')) >>> b.run() # doctest: +SKIP diff --git a/hail/python/hailtop/hailctl/auth/cli.py b/hail/python/hailtop/hailctl/auth/cli.py index f2a6792ad71..c4db0ec028f 100644 --- a/hail/python/hailtop/hailctl/auth/cli.py +++ b/hail/python/hailtop/hailctl/auth/cli.py @@ -4,8 +4,7 @@ from typer import Option as Opt, Argument as Arg import json -from typing import Optional -from typing_extensions import Annotated as Ann +from typing import Optional, Annotated as Ann app = typer.Typer( diff --git a/hail/python/hailtop/hailctl/batch/batch_cli_utils.py b/hail/python/hailtop/hailctl/batch/batch_cli_utils.py index 461abbcd993..b30eb8c050d 100644 --- a/hail/python/hailtop/hailctl/batch/batch_cli_utils.py +++ b/hail/python/hailtop/hailctl/batch/batch_cli_utils.py @@ -2,14 +2,12 @@ from enum import Enum import yaml import csv -from typing import List, Dict, Callable +from typing import List, Dict, Callable, Annotated as Ann import tabulate import io from typer import Option as Opt -from typing_extensions import Annotated as Ann - TableData = List[Dict[str, str]] TABLE_FORMAT_OPTIONS = ['json', 'yaml', 'csv', *tabulate.tabulate_formats] diff --git a/hail/python/hailtop/hailctl/batch/cli.py b/hail/python/hailtop/hailctl/batch/cli.py index 17d2cef9772..ebc1e31fd26 100644 --- a/hail/python/hailtop/hailctl/batch/cli.py +++ b/hail/python/hailtop/hailctl/batch/cli.py @@ -4,8 +4,7 @@ from typer import Option as Opt, Argument as Arg import json -from typing import Optional, List -from typing_extensions import Annotated as Ann +from typing import Optional, List, Annotated as Ann from . import list_batches from . import billing diff --git a/hail/python/hailtop/hailctl/config/cli.py b/hail/python/hailtop/hailctl/config/cli.py index 0d8042bd5e9..273a078fcd7 100644 --- a/hail/python/hailtop/hailctl/config/cli.py +++ b/hail/python/hailtop/hailctl/config/cli.py @@ -3,8 +3,7 @@ import re import warnings -from typing import Optional, Tuple -from typing_extensions import Annotated as Ann +from typing import Optional, Tuple, Annotated as Ann import typer from typer import Argument as Arg diff --git a/hail/python/hailtop/hailctl/dataproc/cli.py b/hail/python/hailtop/hailctl/dataproc/cli.py index 1347617a5f3..f4192886c7f 100644 --- a/hail/python/hailtop/hailctl/dataproc/cli.py +++ b/hail/python/hailtop/hailctl/dataproc/cli.py @@ -3,8 +3,7 @@ import typer from typer import Option as Opt, Argument as Arg -from typing import List, Optional -from typing_extensions import Annotated as Ann +from typing import List, Optional, Annotated as Ann from .connect import connect as dataproc_connect, DataprocConnectService from .submit import submit as dataproc_submit diff --git a/hail/python/hailtop/hailctl/describe.py b/hail/python/hailtop/hailctl/describe.py index 948b614db0a..a3555049ab5 100644 --- a/hail/python/hailtop/hailctl/describe.py +++ b/hail/python/hailtop/hailctl/describe.py @@ -1,7 +1,6 @@ import asyncio import orjson -from typing import List, Optional -from typing_extensions import Annotated as Ann +from typing import List, Optional, Annotated as Ann from os import path from zlib import decompress, MAX_WBITS from statistics import median, mean, stdev diff --git a/hail/python/hailtop/hailctl/dev/cli.py b/hail/python/hailtop/hailctl/dev/cli.py index 635b85079fe..493dfb76afb 100644 --- a/hail/python/hailtop/hailctl/dev/cli.py +++ b/hail/python/hailtop/hailctl/dev/cli.py @@ -2,8 +2,7 @@ import typer import webbrowser -from typing import List, Optional -from typing_extensions import Annotated as Ann +from typing import List, Optional, Annotated as Ann from typer import Option as Opt diff --git a/hail/python/hailtop/hailctl/hdinsight/cli.py b/hail/python/hailtop/hailctl/hdinsight/cli.py index 39fa62eabd1..2846c8b35d9 100644 --- a/hail/python/hailtop/hailctl/hdinsight/cli.py +++ b/hail/python/hailtop/hailctl/hdinsight/cli.py @@ -1,7 +1,6 @@ import subprocess -from typing import Optional, List -from typing_extensions import Annotated as Ann +from typing import Optional, List, Annotated as Ann import typer from typer import Option as Opt, Argument as Arg diff --git a/hail/python/hailtop/utils/utils.py b/hail/python/hailtop/utils/utils.py index b3c22db9bb9..0587812ac8a 100644 --- a/hail/python/hailtop/utils/utils.py +++ b/hail/python/hailtop/utils/utils.py @@ -1,6 +1,6 @@ from typing import (Any, Callable, TypeVar, Awaitable, Mapping, Optional, Type, List, Dict, Iterable, Tuple, Generic, cast) -from typing_extensions import Literal +from typing import Literal from types import TracebackType import concurrent import contextlib diff --git a/hail/python/setup-hailtop.py b/hail/python/setup-hailtop.py index c169348e4fb..4223b8d9e65 100644 --- a/hail/python/setup-hailtop.py +++ b/hail/python/setup-hailtop.py @@ -24,7 +24,7 @@ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", ], - python_requires=">=3.8", + python_requires=">=3.9", entry_points={ 'console_scripts': ['hailctl = hailtop.hailctl.__main__:main'] }, diff --git a/hail/python/setup.py b/hail/python/setup.py index 0f1390911ae..5c75c86588e 100755 --- a/hail/python/setup.py +++ b/hail/python/setup.py @@ -71,7 +71,7 @@ def add_dependencies(fname): "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", ], - python_requires=">=3.8", + python_requires=">=3.9", install_requires=dependencies, entry_points={ 'console_scripts': ['hailctl = hailtop.hailctl.__main__:main'] diff --git a/hail/python/test/hailtop/batch/test_batch.py b/hail/python/test/hailtop/batch/test_batch.py index a5dc6800543..a013c20b8cd 100644 --- a/hail/python/test/hailtop/batch/test_batch.py +++ b/hail/python/test/hailtop/batch/test_batch.py @@ -24,7 +24,7 @@ DOCKER_ROOT_IMAGE = os.environ.get('DOCKER_ROOT_IMAGE', 'ubuntu:20.04') -PYTHON_DILL_IMAGE = 'hailgenetics/python-dill:3.8-slim' +PYTHON_DILL_IMAGE = 'hailgenetics/python-dill:3.9-slim' HAIL_GENETICS_HAIL_IMAGE = os.environ.get('HAIL_GENETICS_HAIL_IMAGE', f'hailgenetics/hail:{pip_version()}') diff --git a/hail/python/test/hailtop/batch/test_batch_pool_executor.py b/hail/python/test/hailtop/batch/test_batch_pool_executor.py index f4ab6cb38b9..b48911d4d06 100644 --- a/hail/python/test/hailtop/batch/test_batch_pool_executor.py +++ b/hail/python/test/hailtop/batch/test_batch_pool_executor.py @@ -8,7 +8,7 @@ from hailtop.utils import sync_sleep_before_try from hailtop.batch_client.client import BatchClient -PYTHON_DILL_IMAGE = 'hailgenetics/python-dill:3.8' +PYTHON_DILL_IMAGE = 'hailgenetics/python-dill:3.9' submitted_batch_ids = [] diff --git a/hail/python/test/hailtop/inter_cloud/generate_copy_test_specs.py b/hail/python/test/hailtop/inter_cloud/generate_copy_test_specs.py index eb9baebb55d..dbf5aa40a69 100644 --- a/hail/python/test/hailtop/inter_cloud/generate_copy_test_specs.py +++ b/hail/python/test/hailtop/inter_cloud/generate_copy_test_specs.py @@ -8,7 +8,7 @@ def remove_prefix(s, prefix): assert s.startswith(prefix), (prefix, s) - return s[len(prefix):] + return s.removeprefix(prefix) async def create_test_file(fs, name, base, path): From 1f170c3090534658bf3f995045b5a49f1b651ac2 Mon Sep 17 00:00:00 2001 From: Dan King Date: Mon, 7 Aug 2023 13:58:47 -0400 Subject: [PATCH 078/180] [batch] do not rename Session to BaseSession b/c BaseSession already exists (#13386) --- hail/python/hailtop/aiocloud/aiogoogle/session.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hail/python/hailtop/aiocloud/aiogoogle/session.py b/hail/python/hailtop/aiocloud/aiogoogle/session.py index be1e6a4c6d2..8a883a23a5c 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/session.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/session.py @@ -1,11 +1,11 @@ from typing import Mapping, Optional, Union -from ..common import Session as BaseSession, AnonymousCloudCredentials +from ..common import Session, AnonymousCloudCredentials from .credentials import GoogleCredentials -class GoogleSession(BaseSession): +class GoogleSession(Session): def __init__(self, *, credentials: Optional[Union[GoogleCredentials, AnonymousCloudCredentials]] = None, credentials_file: Optional[str] = None, params: Optional[Mapping[str, str]] = None, **kwargs): assert credentials is None or credentials_file is None, \ From 97590dc85d883a167b305dc62e90cd4220a938ee Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Mon, 7 Aug 2023 16:11:16 -0400 Subject: [PATCH 079/180] [ci] Add easier way to add all production developers to a dev namespace (#13331) I broke my previous PR into littler pieces some of which has already merged. This PR adds developers from production to test namespaces (only programmatic access, browser OAuth flow does not work yet for test namespaces) and makes it easier to add developers to dev namespaces. --- auth/auth/auth.py | 15 +++++---------- build.yaml | 27 +++++++++++++++++++++++++++ ci/ci/ci.py | 27 +++++++++++++++++++++------ ci/ci/github.py | 10 +++++++--- ci/test/resources/build.yaml | 12 ++++++++++++ 5 files changed, 72 insertions(+), 19 deletions(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index 3cdebf112a8..036bdef9de3 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -427,14 +427,6 @@ async def create_user(request: web.Request, _) -> web.Response: hail_credentials_secret_name = body.get('hail_credentials_secret_name') if (hail_identity or hail_credentials_secret_name) and not is_test_deployment: raise web.HTTPBadRequest(text='Cannot specify an existing hail identity for a new user') - if hail_credentials_secret_name: - try: - k8s_cache: K8sCache = request.app['k8s_cache'] - await k8s_cache.read_secret(hail_credentials_secret_name, DEFAULT_NAMESPACE) - except kubernetes_asyncio.client.rest.ApiException as e: - raise web.HTTPBadRequest( - text=f'hail credentials secret name specified but was not found in namespace {DEFAULT_NAMESPACE}: {hail_credentials_secret_name}' - ) from e try: await insert_new_user( @@ -585,8 +577,11 @@ async def post_create_user(request: web.Request, _) -> web.HTTPFound: @routes.get('/api/v1alpha/users') -@authenticated_devs_only -async def rest_get_users(request: web.Request, _) -> web.Response: +@authenticated_users_only +async def rest_get_users(request: web.Request, userdata: UserData) -> web.Response: + if userdata['is_developer'] != 1 and userdata['username'] != 'ci': + raise web.HTTPUnauthorized() + db: Database = request.app['db'] _query = ''' SELECT id, username, login_id, state, is_developer, is_service_account, hail_identity diff --git a/build.yaml b/build.yaml index a7553b64797..55f228d95ff 100644 --- a/build.yaml +++ b/build.yaml @@ -2223,6 +2223,33 @@ steps: - batch_database - deploy_auth - create_certs + - kind: runImage + name: add_developers + image: + valueFrom: hailgenetics_hailtop_image.image + script: | + set -ex + {% for user in code.get("developers", []) %} + {% if user['username'] != 'test-dev' %} + hailctl auth create-user \ + --developer \ + --hail-identity {{ user["hail_identity"] }} \ + --hail-credentials-secret-name {{ user["username"] }}-gsa-key \ + {{ user["username"] }} {{ user["login_id"] }} + {% endif %} + {% endfor %} + secrets: + - name: test-dev-tokens + namespace: + valueFrom: default_ns.name + mountPath: /user-tokens + scopes: + - dev + - test + dependsOn: + - default_ns + - hailgenetics_hailtop_image + - deploy_batch - kind: runImage name: create_billing_projects resources: diff --git a/ci/ci/ci.py b/ci/ci/ci.py index a3fa29fcb31..eaa2aa7a0f5 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -30,11 +30,12 @@ ) from gear.profiling import install_profiler_if_requested from hailtop import aiotools, httpx +from hailtop.auth import hail_credentials from hailtop.batch_client.aioclient import Batch, BatchClient from hailtop.config import get_deploy_config from hailtop.hail_logging import AccessLogger from hailtop.tls import internal_server_ssl_context -from hailtop.utils import collect_agen, humanize_timedelta_msecs, periodically_call +from hailtop.utils import collect_agen, humanize_timedelta_msecs, periodically_call, retry_transient_errors from web_common import render_template, set_message, setup_aiohttp_jinja2, setup_common_static_routes from .constants import AUTHORIZED_USERS, TEAMS @@ -51,10 +52,7 @@ deploy_config = get_deploy_config() -watched_branches: List[WatchedBranch] = [ - WatchedBranch(index, FQBranch.from_short_str(bss), deployable, mergeable) - for (index, [bss, deployable, mergeable]) in enumerate(json.loads(os.environ.get('HAIL_WATCHED_BRANCHES', '[]'))) -] +watched_branches: List[WatchedBranch] = [] routes = web.RouteTableDef() @@ -741,7 +739,8 @@ async def update_loop(app): async def on_startup(app): - app['client_session'] = httpx.client_session() + client_session = httpx.client_session() + app['client_session'] = client_session app['github_client'] = gh_aiohttp.GitHubAPI(app['client_session'], 'ci', oauth_token=oauth_token) app['batch_client'] = await BatchClient.create('ci') @@ -765,6 +764,22 @@ async def on_startup(app): app['task_manager'].ensure_future(periodically_call(10, update_envoy_configs, app['db'], k8s_client)) app['task_manager'].ensure_future(periodically_call(10, cleanup_expired_namespaces, app['db'])) + headers = await hail_credentials().auth_headers() + users = await retry_transient_errors( + client_session.get_read_json, + deploy_config.url('auth', '/api/v1alpha/users'), + headers=headers, + ) + app['developers'] = [u for u in users if u['is_developer'] == 1 and u['state'] == 'active'] + + global watched_branches + watched_branches = [ + WatchedBranch(index, FQBranch.from_short_str(bss), deployable, mergeable, app['developers']) + for (index, [bss, deployable, mergeable]) in enumerate( + json.loads(os.environ.get('HAIL_WATCHED_BRANCHES', '[]')) + ) + ] + async def on_cleanup(app): try: diff --git a/ci/ci/github.py b/ci/ci/github.py index 9161b2fa212..8c2c9329178 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -8,7 +8,7 @@ import secrets from enum import Enum from shlex import quote as shq -from typing import Dict, Optional, Set, Union +from typing import Dict, List, Optional, Set, Union import aiohttp import gidgethub @@ -669,11 +669,12 @@ def checkout_script(self): class WatchedBranch(Code): - def __init__(self, index, branch, deployable, mergeable): + def __init__(self, index, branch, deployable, mergeable, developers): self.index: int = index self.branch: FQBranch = branch self.deployable: bool = deployable self.mergeable: bool = mergeable + self.developers: List[dict] = developers self.prs: Dict[int, PR] = {} self.sha: Optional[str] = None @@ -713,6 +714,7 @@ def config(self): 'repo': self.branch.repo.short_str(), 'repo_url': self.branch.repo.url, 'sha': self.sha, + 'developers': self.developers, } async def notify_github_changed(self, app): @@ -993,10 +995,11 @@ def checkout_script(self): class UnwatchedBranch(Code): - def __init__(self, branch, sha, userdata, extra_config=None): + def __init__(self, branch, sha, userdata, developers, extra_config=None): self.branch = branch self.user = userdata['username'] self.namespace = userdata['namespace_name'] + self.developers = developers self.sha = sha self.extra_config = extra_config @@ -1016,6 +1019,7 @@ def config(self): 'repo_url': self.branch.repo.url, 'sha': self.sha, 'user': self.user, + 'developers': self.developers, } if self.extra_config is not None: config.update(self.extra_config) diff --git a/ci/test/resources/build.yaml b/ci/test/resources/build.yaml index 448c9b774b5..ee253bc51e8 100644 --- a/ci/test/resources/build.yaml +++ b/ci/test/resources/build.yaml @@ -295,3 +295,15 @@ steps: - ci_utils_image - default_ns - deploy_hello + - kind: runImage + name: test_jinja_state_contains_developers + image: + valueFrom: hail_ubuntu_image.image + script: | + set -ex + + {% for user in code['developers'] %} + echo {{ user['username'] }} + {% endfor %} + dependsOn: + - hail_ubuntu_image From d5f94c651f3324ed68eca70045d3c00acc0176ad Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Mon, 7 Aug 2023 17:43:09 -0400 Subject: [PATCH 080/180] [batch] Stream job logs in the batch front-end (#13322) Fixes #13328. See that issue for context. See [here](https://internal.hail.is/dgoldste/batch/batches/5/jobs/1) for an example of a job log that would currently OOM production pods. --- batch/batch/file_store.py | 6 +- batch/batch/front_end/front_end.py | 120 ++++++++++++++++++----- batch/batch/front_end/templates/job.html | 27 ++++- 3 files changed, 123 insertions(+), 30 deletions(-) diff --git a/batch/batch/file_store.py b/batch/batch/file_store.py index 2e4a13baec5..a6310928857 100644 --- a/batch/batch/file_store.py +++ b/batch/batch/file_store.py @@ -4,7 +4,7 @@ import pandas as pd -from hailtop.aiotools.fs import AsyncFS +from hailtop.aiotools.fs import AsyncFS, ReadableStream from .batch_format_version import BatchFormatVersion from .globals import BATCH_FORMAT_VERSION @@ -44,9 +44,9 @@ def jvm_profile_path(self, format_version, batch_id, job_id, attempt_id, task): return f'{self.batch_log_dir(batch_id)}/{job_id}/{task}/jvm_profile.html' return f'{self.batch_log_dir(batch_id)}/{job_id}/{attempt_id}/{task}/jvm_profile.html' - async def read_log_file(self, format_version, batch_id, job_id, attempt_id, task) -> bytes: + async def open_log_file(self, format_version, batch_id, job_id, attempt_id, task) -> ReadableStream: url = self.log_path(format_version, batch_id, job_id, attempt_id, task) - return await self.fs.read(url) + return await self.fs.open(url) async def write_log_file(self, format_version, batch_id, job_id, attempt_id, task, data: bytes): url = self.log_path(format_version, batch_id, job_id, attempt_id, task) diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index e58caf65c86..7246753482f 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -2,6 +2,7 @@ import base64 import collections import datetime +import io import json import logging import os @@ -44,6 +45,7 @@ from gear.database import CallError from gear.profiling import install_profiler_if_requested from hailtop import aiotools, dictfix, httpx, version +from hailtop.aiotools.fs import ReadableStream from hailtop.batch_client.parse import parse_cpu_in_mcpu, parse_memory_in_bytes, parse_storage_in_bytes from hailtop.config import get_deploy_config from hailtop.hail_logging import AccessLogger @@ -343,7 +345,7 @@ async def _get_job_record(app, batch_id, job_id): return record -def job_tasks_from_spec(record): +def job_tasks_from_spec(record) -> List[str]: batch_format_version = BatchFormatVersion(record['format_version']) spec = json.loads(record['spec']) tasks = [] @@ -377,29 +379,62 @@ def attempt_id_from_spec(record) -> Optional[str]: return record['attempt_id'] or record['last_cancelled_attempt_id'] -async def _get_job_container_log_from_worker(client_session, batch_id, job_id, container, ip_address) -> bytes: +class ReadableStreamFromBytes(ReadableStream): + def __init__(self, data: bytes): + super().__init__() + self.strm = io.BytesIO(data) + + async def read(self, n: int = -1) -> bytes: + return self.strm.read(n) + + async def readexactly(self, n: int) -> bytes: + raise NotImplementedError + + async def _wait_closed(self): + self.strm.close() + + +class ReadableStreamFromAiohttpClientResponse(ReadableStream): + def __init__(self, resp: aiohttp.ClientResponse): + super().__init__() + self.resp = resp + + async def read(self, n: int = -1) -> bytes: + return await self.resp.content.read(n) + + async def readexactly(self, n: int) -> bytes: + return await self.resp.content.readexactly(n) + + async def _wait_closed(self): + await self.resp.release() + + +async def _get_job_container_log_from_worker( + client_session: httpx.ClientSession, batch_id: int, job_id: int, container: str, ip_address: str +) -> ReadableStream: try: - return await retry_transient_errors( - client_session.get_read, + resp = await retry_transient_errors( + client_session.get, f'http://{ip_address}:5000/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log/{container}', ) + return ReadableStreamFromAiohttpClientResponse(resp) except aiohttp.ClientResponseError: log.exception(f'while getting log for {(batch_id, job_id)}') - return b'ERROR: encountered a problem while fetching the log' + return ReadableStreamFromBytes(b'ERROR: encountered a problem while fetching the log') async def _read_job_container_log_from_cloud_storage( file_store: FileStore, batch_format_version: BatchFormatVersion, batch_id, job_id, container, attempt_id -) -> bytes: +) -> ReadableStream: try: - return await file_store.read_log_file(batch_format_version, batch_id, job_id, attempt_id, container) + return await file_store.open_log_file(batch_format_version, batch_id, job_id, attempt_id, container) except FileNotFoundError: id = (batch_id, job_id) log.exception(f'missing log file for {id} and container {container}') - return b'ERROR: could not find log file' + return ReadableStreamFromBytes(b'ERROR: could not find log file') -async def _get_job_container_log(app, batch_id, job_id, container, job_record) -> Optional[bytes]: +async def _get_job_container_log(app, batch_id, job_id, container, job_record) -> Optional[ReadableStream]: if not has_resource_available(job_record): return None @@ -421,10 +456,28 @@ async def _get_job_container_log(app, batch_id, job_id, container, job_record) - ) -async def _get_job_log(app, batch_id, job_id) -> Dict[str, Optional[bytes]]: +PossiblyTruncatedLog = Tuple[bytes, bool] + + +async def _get_job_log(app, batch_id, job_id) -> Dict[str, Optional[PossiblyTruncatedLog]]: record = await _get_job_record(app, batch_id, job_id) containers = job_tasks_from_spec(record) - logs = await asyncio.gather(*[_get_job_container_log(app, batch_id, job_id, c, record) for c in containers]) + + async def load_up_to_fifty_kib(app, batch_id, job_id, c, record) -> Optional[PossiblyTruncatedLog]: + s = await _get_job_container_log(app, batch_id, job_id, c, record) + if s is None: + return None + fifty_kib = 50 * 1024 + async with s: + log = await s.read(fifty_kib + 1) + if len(log) == fifty_kib + 1: + return (log[:fifty_kib], True) + + return (log, False) + + logs: List[Optional[PossiblyTruncatedLog]] = await asyncio.gather( + *(load_up_to_fifty_kib(app, batch_id, job_id, c, record) for c in containers) + ) return dict(zip(containers, logs)) @@ -591,11 +644,14 @@ async def _get_full_job_status(app, record): @add_metadata_to_request async def get_job_log(request: web.Request, _, batch_id: int) -> web.Response: job_id = int(request.match_info['job_id']) - job_log_bytes = await _get_job_log(request.app, batch_id, job_id) + job_logs = await _get_job_log(request.app, batch_id, job_id) job_log_strings: Dict[str, Optional[str]] = {} - for container, log in job_log_bytes.items(): + for container, log in job_logs.items(): try: - job_log_strings[container] = log.decode('utf-8') if log is not None else None + if log is None: + job_log_strings[container] = None + else: + job_log_strings[container] = log[0].decode('utf-8') except UnicodeDecodeError as e: raise web.HTTPBadRequest( reason=f'log for container {container} is not valid UTF-8, upgrade your hail version to download the log' @@ -611,14 +667,22 @@ async def get_job_container_log(request, batch_id): containers = job_tasks_from_spec(record) if container not in containers: raise web.HTTPBadRequest(reason=f'unknown container {container}') - job_log = await _get_job_container_log(app, batch_id, job_id, container, record) - return web.Response(body=job_log) + container_log = await _get_job_container_log(app, batch_id, job_id, container, record) + + resp = web.StreamResponse() + await resp.prepare(request) + if container_log is not None: + async with container_log: + while b := await container_log.read(1024**2): + await resp.write(b) + await resp.write_eof() + return resp @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log/{container}') @rest_billing_project_users_only @add_metadata_to_request -async def rest_get_job_container_log(request, _, batch_id) -> web.Response: +async def rest_get_job_container_log(request, _, batch_id) -> web.StreamResponse: return await get_job_container_log(request, batch_id) @@ -2064,7 +2128,7 @@ async def ui_get_job(request, userdata, batch_id): app = request.app job_id = int(request.match_info['job_id']) - job, attempts, job_log_bytes, resource_usage = await asyncio.gather( + job, attempts, job_logs, resource_usage = await asyncio.gather( _get_job(app, batch_id, job_id), _get_attempts(app, batch_id, job_id), _get_job_log(app, batch_id, job_id), @@ -2143,12 +2207,19 @@ async def ui_get_job(request, userdata, batch_id): # Not all logs will be proper utf-8 but we attempt to show them as # str or else Jinja will present them surrounded by b'' - job_log_strings_or_bytes = {} - for container, log in job_log_bytes.items(): - try: - job_log_strings_or_bytes[container] = log.decode('utf-8') if log is not None else None - except UnicodeDecodeError: - job_log_strings_or_bytes[container] = log + job_log_strings_or_bytes: Dict[str, Union[str, bytes, None]] = {} + truncated_logs = set() + for container, log in job_logs.items(): + if log is None: + job_log_strings_or_bytes[container] = None + else: + log_content, is_truncated = log + if is_truncated: + truncated_logs.add(container) + try: + job_log_strings_or_bytes[container] = log_content.decode('utf-8') + except UnicodeDecodeError: + job_log_strings_or_bytes[container] = log_content page_context = { 'batch_id': batch_id, @@ -2166,6 +2237,7 @@ async def ui_get_job(request, userdata, batch_id): resource_usage, memory_limit_bytes, io_storage_limit_bytes, non_io_storage_limit_bytes ), 'has_jvm_profile': has_jvm_profile, + 'truncated_logs': truncated_logs, } return await render_template('batch', request, userdata, 'job.html', page_context) diff --git a/batch/batch/front_end/templates/job.html b/batch/batch/front_end/templates/job.html index 955978ef97e..47104eb4027 100644 --- a/batch/batch/front_end/templates/job.html +++ b/batch/batch/front_end/templates/job.html @@ -137,7 +137,14 @@

Logs

{% if 'input' in job_log or 'input' in step_errors %}

Input

{% if 'input' in job_log %} -

Log

+

Log + + + +

+{% if 'input' in truncated_logs %} +Log too long to display. Download the full log +{% endif %}
{{ job_log['input'] }}
{% endif %} {% if 'input' in step_errors and step_errors['input'] is not none %} @@ -149,7 +156,14 @@

Error

{% if 'main' in job_log or 'main' in step_errors %}

Main

{% if 'main' in job_log %} -

Log

+

Log + + + +

+{% if 'main' in truncated_logs %} +Log too long to display. Download the full log +{% endif %}
{{ job_log['main'] }}
{% endif %} {% if 'main' in step_errors and step_errors['main'] is not none %} @@ -161,7 +175,14 @@

Error

{% if 'output' in job_log or 'output' in step_errors %}

Output

{% if 'output' in job_log %} -

Log

+

Log + + + +

+{% if 'output' in truncated_logs %} +Log too long to display. Download the full log +{% endif %}
{{ job_log['output'] }}
{% endif %} {% if 'output' in step_errors and step_errors['output'] is not none %} From b7442e86df82228dd24059c51d271d151657e630 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Mon, 7 Aug 2023 19:03:43 -0400 Subject: [PATCH 081/180] [vds/combiner] Teach VDS combiner how to handle custom call fields (#13385) Add the call_fields argument. Much like refrence entries, when passing a VDS to the combiner, we check it's call fields to ensure that there is a match between the passed argument and the VDS's call fields. --- hail/python/hail/vds/combiner/combine.py | 2 +- .../vds/combiner/variant_dataset_combiner.py | 39 ++++++++++++++++--- hail/python/test/hail/vds/test_combiner.py | 17 ++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/hail/python/hail/vds/combiner/combine.py b/hail/python/hail/vds/combiner/combine.py index 0deeafea3f0..e0089d05bf4 100644 --- a/hail/python/hail/vds/combiner/combine.py +++ b/hail/python/hail/vds/combiner/combine.py @@ -50,7 +50,7 @@ def make_entry_struct(e, alleles_len, has_non_ref, row): 'LPGT', 'PGT'} if 'GT' not in e: - raise hl.utils.FatalError("the Hail GVCF combiner expects GVCFs to have a 'GT' field in FORMAT.") + raise hl.utils.FatalError("the Hail VDS combiner expects input GVCFs to have a 'GT' field in FORMAT.") handled_fields['LA'] = hl.range(0, alleles_len - hl.if_else(has_non_ref, 1, 0)) handled_fields['LGT'] = get_lgt(e, alleles_len, has_non_ref, row) diff --git a/hail/python/hail/vds/combiner/variant_dataset_combiner.py b/hail/python/hail/vds/combiner/variant_dataset_combiner.py index cc59379bf58..06ab7769848 100644 --- a/hail/python/hail/vds/combiner/variant_dataset_combiner.py +++ b/hail/python/hail/vds/combiner/variant_dataset_combiner.py @@ -4,6 +4,7 @@ import os import sys import uuid +from itertools import chain from math import floor, log from typing import Collection, Dict, List, NamedTuple, Optional, Union @@ -155,8 +156,8 @@ class VariantDatasetCombiner: # pylint: disable=too-many-instance-attributes A list of intervals defining how to partition the GVCF files. The same partitioning is used for all GVCF files. Finer partitioning yields more parallelism but less work per task. gvcf_info_to_keep : :class:`list` of :class:`str` or :obj:`None` - GVCF ``INFO`` fields to keep in the ``gvcf_info`` entry field. By default, all fields are - kept except ``END`` and ``DP`` are kept. + GVCF ``INFO`` fields to keep in the ``gvcf_info`` entry field. By default, all fields + except ``END`` and ``DP`` are kept. gvcf_reference_entry_fields_to_keep : :class:`list` of :class:`str` or :obj:`None` Genotype fields to keep in the reference table. If empty, the first 10,000 reference block rows of ``mt`` will be sampled and all fields found to be defined other than ``GT``, ``AD``, @@ -196,6 +197,7 @@ class VariantDatasetCombiner: # pylint: disable=too-many-instance-attributes '_gvcf_import_intervals', '_gvcf_info_to_keep', '_gvcf_reference_entry_fields_to_keep', + '_call_fields', ] __slots__ = tuple(__serialized_slots__ + ['_uuid', '_job_id', '__intervals_cache']) @@ -212,6 +214,7 @@ def __init__(self, target_records: int = _default_target_records, gvcf_batch_size: int = _default_gvcf_batch_size, contig_recoding: Optional[Dict[str, str]] = None, + call_fields: Collection[str], vdses: List[VDSMetadata], gvcfs: List[str], gvcf_sample_names: Optional[List[str]] = None, @@ -248,6 +251,7 @@ def __init__(self, self._branch_factor = branch_factor self._target_records = target_records self._contig_recoding = contig_recoding + self._call_fields = list(call_fields) self._vdses = collections.defaultdict(list) for vds in vdses: self._vdses[max(1, floor(log(vds.n_samples, self._branch_factor)))].append(vds) @@ -367,6 +371,7 @@ def to_dict(self) -> dict: 'gvcf_reference_entry_fields_to_keep': None if self._gvcf_reference_entry_fields_to_keep is None else list(self._gvcf_reference_entry_fields_to_keep), + 'call_fields': self._call_fields, 'vdses': [md for i in sorted(self._vdses, reverse=True) for md in self._vdses[i]], 'gvcfs': self._gvcfs, 'gvcf_sample_names': self._gvcf_sample_names, @@ -513,6 +518,7 @@ def _step_gvcfs(self): idx_and_path[1], idx_and_path[0], interval.contig, interval.start, interval.end, header_info, + call_fields=self._call_fields, array_elements_required=False, reference_genome=self._reference_genome, contig_recoding=self._contig_recoding), @@ -532,6 +538,7 @@ def _step_gvcfs(self): idx_and_path[1], idx_and_path[0], interval.contig, interval.start, interval.end, header_info, + call_fields=self._call_fields, array_elements_required=False, reference_genome=self._reference_genome, contig_recoding=self._contig_recoding), @@ -590,6 +597,7 @@ def new_combiner(*, gvcf_sample_names: Optional[List[str]] = None, gvcf_info_to_keep: Optional[Collection[str]] = None, gvcf_reference_entry_fields_to_keep: Optional[Collection[str]] = None, + call_fields: Collection[str] = ['PGT'], branch_factor: int = VariantDatasetCombiner._default_branch_factor, target_records: int = VariantDatasetCombiner._default_target_records, gvcf_batch_size: Optional[int] = None, @@ -694,12 +702,28 @@ def maybe_load_from_saved_path(save_path: str) -> Optional[VariantDatasetCombine vds = None gvcf_type = None if vds_paths: + # sync up gvcf_reference_entry_fields_to_keep and they reference entry types from the VDS vds = hl.vds.read_vds(vds_paths[0], _warn_no_ref_block_max_length=False) - ref_entry_tmp = set(vds.reference_data.entry) - {'END'} - if gvcf_reference_entry_fields_to_keep is not None and ref_entry_tmp != gvcf_reference_entry_fields_to_keep: + vds_ref_entry = set(vds.reference_data.entry) - {'END'} + if gvcf_reference_entry_fields_to_keep is not None and vds_ref_entry != gvcf_reference_entry_fields_to_keep: warning("Mismatch between 'gvcf_reference_entry_fields' to keep and VDS reference data " - "entry types. Overwriting with types from supplied VDS.") - gvcf_reference_entry_fields_to_keep = ref_entry_tmp + "entry types. Overwriting with reference entry fields from supplied VDS.\n" + f" VDS reference entry fields : {sorted(vds_ref_entry)}\n" + f" requested reference entry fields: {sorted(gvcf_reference_entry_fields_to_keep)}") + gvcf_reference_entry_fields_to_keep = vds_ref_entry + + # sync up call_fields and call fields present in the VDS + all_entry_types = chain(vds.reference_data._type.entry_type.items(), + vds.variant_data._type.entry_type.items()) + vds_call_fields = {name for name, typ in all_entry_types if typ == hl.tcall} - {'LGT', 'GT'} + if 'LPGT' in vds_call_fields: + vds_call_fields = (vds_call_fields - {'LPGT'}) | {'PGT'} + if set(call_fields) != vds_call_fields: + warning("Mismatch between 'call_fields' and VDS call fields. " + "Overwriting with call fields from supplied VDS.\n" + f" VDS call fields : {sorted(vds_call_fields)}\n" + f" requested call fields: {sorted(call_fields)}\n") + call_fields = vds_call_fields if gvcf_paths: mt = hl.import_vcf(gvcf_paths[0], header_file=gvcf_external_header, force_bgz=True, @@ -739,6 +763,8 @@ def maybe_load_from_saved_path(save_path: str) -> Optional[VariantDatasetCombine if gvcf_reference_entry_fields_to_keep is not None: for field in sorted(gvcf_reference_entry_fields_to_keep): sha.update(field.encode()) + for call_field in sorted(call_fields): + sha.update(call_field.encode()) if contig_recoding is not None: for key, value in sorted(contig_recoding.items()): sha.update(key.encode()) @@ -775,6 +801,7 @@ def maybe_load_from_saved_path(save_path: str) -> Optional[VariantDatasetCombine target_records=target_records, gvcf_batch_size=gvcf_batch_size, contig_recoding=contig_recoding, + call_fields=call_fields, vdses=vdses, gvcfs=gvcf_paths, gvcf_import_intervals=intervals, diff --git a/hail/python/test/hail/vds/test_combiner.py b/hail/python/test/hail/vds/test_combiner.py index bb3651007e7..fc2f51169d6 100644 --- a/hail/python/test/hail/vds/test_combiner.py +++ b/hail/python/test/hail/vds/test_combiner.py @@ -192,3 +192,20 @@ def test_ref_block_max_len_propagates_in_combiner(): reference_genome='GRCh38').run() vds = hl.vds.read_vds(final_path) assert hl.vds.VariantDataset.ref_block_max_length_field in vds.reference_data.globals + + +def test_custom_call_fields(): + _paths = ['gvcfs/HG00096.g.vcf.gz', 'gvcfs/HG00268.g.vcf.gz'] + paths = [resource(p) for p in _paths] + parts = [ + hl.Interval(start=hl.Locus('chr20', 17821257, reference_genome='GRCh38'), + end=hl.Locus('chr20', 21144633, reference_genome='GRCh38'), + includes_end=True), + ] + with hl.TemporaryDirectory() as tmpdir: + out = os.path.join(tmpdir, 'out.vds') + hl.vds.new_combiner(temp_path=tmpdir, output_path=out, gvcf_paths=paths, intervals=parts, call_fields=[], reference_genome='GRCh38').run() + comb = hl.vds.read_vds(out) + + assert 'LPGT' in comb.variant_data.entry + assert comb.variant_data.LPGT.dtype == hl.tstr From a39935207cbd232d4003c7f8a2d242ad12eda490 Mon Sep 17 00:00:00 2001 From: Dan King Date: Mon, 7 Aug 2023 20:12:23 -0400 Subject: [PATCH 082/180] [batch] novel way for GCR to say 403 (#13388) --- batch/batch/worker/worker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index b746bfd8e50..aef542c3b2c 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -556,6 +556,7 @@ async def pull(): raise ImageCannotBePulled from e if e.status == 500 and ( 'Permission "artifactregistry.repositories.downloadArtifacts" denied on resource' in e.message + or 'Caller does not have permission' in e.message or 'unauthorized' in e.message ): raise ImageCannotBePulled from e From d5b045c30fd622256ab9708090aff840a547c2f6 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 8 Aug 2023 11:11:17 -0400 Subject: [PATCH 083/180] Revert "[batch] Stream job logs in the batch front-end" (#13392) Reverts hail-is/hail#13322 --- batch/batch/file_store.py | 6 +- batch/batch/front_end/front_end.py | 120 +++++------------------ batch/batch/front_end/templates/job.html | 27 +---- 3 files changed, 30 insertions(+), 123 deletions(-) diff --git a/batch/batch/file_store.py b/batch/batch/file_store.py index a6310928857..2e4a13baec5 100644 --- a/batch/batch/file_store.py +++ b/batch/batch/file_store.py @@ -4,7 +4,7 @@ import pandas as pd -from hailtop.aiotools.fs import AsyncFS, ReadableStream +from hailtop.aiotools.fs import AsyncFS from .batch_format_version import BatchFormatVersion from .globals import BATCH_FORMAT_VERSION @@ -44,9 +44,9 @@ def jvm_profile_path(self, format_version, batch_id, job_id, attempt_id, task): return f'{self.batch_log_dir(batch_id)}/{job_id}/{task}/jvm_profile.html' return f'{self.batch_log_dir(batch_id)}/{job_id}/{attempt_id}/{task}/jvm_profile.html' - async def open_log_file(self, format_version, batch_id, job_id, attempt_id, task) -> ReadableStream: + async def read_log_file(self, format_version, batch_id, job_id, attempt_id, task) -> bytes: url = self.log_path(format_version, batch_id, job_id, attempt_id, task) - return await self.fs.open(url) + return await self.fs.read(url) async def write_log_file(self, format_version, batch_id, job_id, attempt_id, task, data: bytes): url = self.log_path(format_version, batch_id, job_id, attempt_id, task) diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index 7246753482f..e58caf65c86 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -2,7 +2,6 @@ import base64 import collections import datetime -import io import json import logging import os @@ -45,7 +44,6 @@ from gear.database import CallError from gear.profiling import install_profiler_if_requested from hailtop import aiotools, dictfix, httpx, version -from hailtop.aiotools.fs import ReadableStream from hailtop.batch_client.parse import parse_cpu_in_mcpu, parse_memory_in_bytes, parse_storage_in_bytes from hailtop.config import get_deploy_config from hailtop.hail_logging import AccessLogger @@ -345,7 +343,7 @@ async def _get_job_record(app, batch_id, job_id): return record -def job_tasks_from_spec(record) -> List[str]: +def job_tasks_from_spec(record): batch_format_version = BatchFormatVersion(record['format_version']) spec = json.loads(record['spec']) tasks = [] @@ -379,62 +377,29 @@ def attempt_id_from_spec(record) -> Optional[str]: return record['attempt_id'] or record['last_cancelled_attempt_id'] -class ReadableStreamFromBytes(ReadableStream): - def __init__(self, data: bytes): - super().__init__() - self.strm = io.BytesIO(data) - - async def read(self, n: int = -1) -> bytes: - return self.strm.read(n) - - async def readexactly(self, n: int) -> bytes: - raise NotImplementedError - - async def _wait_closed(self): - self.strm.close() - - -class ReadableStreamFromAiohttpClientResponse(ReadableStream): - def __init__(self, resp: aiohttp.ClientResponse): - super().__init__() - self.resp = resp - - async def read(self, n: int = -1) -> bytes: - return await self.resp.content.read(n) - - async def readexactly(self, n: int) -> bytes: - return await self.resp.content.readexactly(n) - - async def _wait_closed(self): - await self.resp.release() - - -async def _get_job_container_log_from_worker( - client_session: httpx.ClientSession, batch_id: int, job_id: int, container: str, ip_address: str -) -> ReadableStream: +async def _get_job_container_log_from_worker(client_session, batch_id, job_id, container, ip_address) -> bytes: try: - resp = await retry_transient_errors( - client_session.get, + return await retry_transient_errors( + client_session.get_read, f'http://{ip_address}:5000/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log/{container}', ) - return ReadableStreamFromAiohttpClientResponse(resp) except aiohttp.ClientResponseError: log.exception(f'while getting log for {(batch_id, job_id)}') - return ReadableStreamFromBytes(b'ERROR: encountered a problem while fetching the log') + return b'ERROR: encountered a problem while fetching the log' async def _read_job_container_log_from_cloud_storage( file_store: FileStore, batch_format_version: BatchFormatVersion, batch_id, job_id, container, attempt_id -) -> ReadableStream: +) -> bytes: try: - return await file_store.open_log_file(batch_format_version, batch_id, job_id, attempt_id, container) + return await file_store.read_log_file(batch_format_version, batch_id, job_id, attempt_id, container) except FileNotFoundError: id = (batch_id, job_id) log.exception(f'missing log file for {id} and container {container}') - return ReadableStreamFromBytes(b'ERROR: could not find log file') + return b'ERROR: could not find log file' -async def _get_job_container_log(app, batch_id, job_id, container, job_record) -> Optional[ReadableStream]: +async def _get_job_container_log(app, batch_id, job_id, container, job_record) -> Optional[bytes]: if not has_resource_available(job_record): return None @@ -456,28 +421,10 @@ async def _get_job_container_log(app, batch_id, job_id, container, job_record) - ) -PossiblyTruncatedLog = Tuple[bytes, bool] - - -async def _get_job_log(app, batch_id, job_id) -> Dict[str, Optional[PossiblyTruncatedLog]]: +async def _get_job_log(app, batch_id, job_id) -> Dict[str, Optional[bytes]]: record = await _get_job_record(app, batch_id, job_id) containers = job_tasks_from_spec(record) - - async def load_up_to_fifty_kib(app, batch_id, job_id, c, record) -> Optional[PossiblyTruncatedLog]: - s = await _get_job_container_log(app, batch_id, job_id, c, record) - if s is None: - return None - fifty_kib = 50 * 1024 - async with s: - log = await s.read(fifty_kib + 1) - if len(log) == fifty_kib + 1: - return (log[:fifty_kib], True) - - return (log, False) - - logs: List[Optional[PossiblyTruncatedLog]] = await asyncio.gather( - *(load_up_to_fifty_kib(app, batch_id, job_id, c, record) for c in containers) - ) + logs = await asyncio.gather(*[_get_job_container_log(app, batch_id, job_id, c, record) for c in containers]) return dict(zip(containers, logs)) @@ -644,14 +591,11 @@ async def _get_full_job_status(app, record): @add_metadata_to_request async def get_job_log(request: web.Request, _, batch_id: int) -> web.Response: job_id = int(request.match_info['job_id']) - job_logs = await _get_job_log(request.app, batch_id, job_id) + job_log_bytes = await _get_job_log(request.app, batch_id, job_id) job_log_strings: Dict[str, Optional[str]] = {} - for container, log in job_logs.items(): + for container, log in job_log_bytes.items(): try: - if log is None: - job_log_strings[container] = None - else: - job_log_strings[container] = log[0].decode('utf-8') + job_log_strings[container] = log.decode('utf-8') if log is not None else None except UnicodeDecodeError as e: raise web.HTTPBadRequest( reason=f'log for container {container} is not valid UTF-8, upgrade your hail version to download the log' @@ -667,22 +611,14 @@ async def get_job_container_log(request, batch_id): containers = job_tasks_from_spec(record) if container not in containers: raise web.HTTPBadRequest(reason=f'unknown container {container}') - container_log = await _get_job_container_log(app, batch_id, job_id, container, record) - - resp = web.StreamResponse() - await resp.prepare(request) - if container_log is not None: - async with container_log: - while b := await container_log.read(1024**2): - await resp.write(b) - await resp.write_eof() - return resp + job_log = await _get_job_container_log(app, batch_id, job_id, container, record) + return web.Response(body=job_log) @routes.get('/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log/{container}') @rest_billing_project_users_only @add_metadata_to_request -async def rest_get_job_container_log(request, _, batch_id) -> web.StreamResponse: +async def rest_get_job_container_log(request, _, batch_id) -> web.Response: return await get_job_container_log(request, batch_id) @@ -2128,7 +2064,7 @@ async def ui_get_job(request, userdata, batch_id): app = request.app job_id = int(request.match_info['job_id']) - job, attempts, job_logs, resource_usage = await asyncio.gather( + job, attempts, job_log_bytes, resource_usage = await asyncio.gather( _get_job(app, batch_id, job_id), _get_attempts(app, batch_id, job_id), _get_job_log(app, batch_id, job_id), @@ -2207,19 +2143,12 @@ async def ui_get_job(request, userdata, batch_id): # Not all logs will be proper utf-8 but we attempt to show them as # str or else Jinja will present them surrounded by b'' - job_log_strings_or_bytes: Dict[str, Union[str, bytes, None]] = {} - truncated_logs = set() - for container, log in job_logs.items(): - if log is None: - job_log_strings_or_bytes[container] = None - else: - log_content, is_truncated = log - if is_truncated: - truncated_logs.add(container) - try: - job_log_strings_or_bytes[container] = log_content.decode('utf-8') - except UnicodeDecodeError: - job_log_strings_or_bytes[container] = log_content + job_log_strings_or_bytes = {} + for container, log in job_log_bytes.items(): + try: + job_log_strings_or_bytes[container] = log.decode('utf-8') if log is not None else None + except UnicodeDecodeError: + job_log_strings_or_bytes[container] = log page_context = { 'batch_id': batch_id, @@ -2237,7 +2166,6 @@ async def ui_get_job(request, userdata, batch_id): resource_usage, memory_limit_bytes, io_storage_limit_bytes, non_io_storage_limit_bytes ), 'has_jvm_profile': has_jvm_profile, - 'truncated_logs': truncated_logs, } return await render_template('batch', request, userdata, 'job.html', page_context) diff --git a/batch/batch/front_end/templates/job.html b/batch/batch/front_end/templates/job.html index 47104eb4027..955978ef97e 100644 --- a/batch/batch/front_end/templates/job.html +++ b/batch/batch/front_end/templates/job.html @@ -137,14 +137,7 @@

Logs

{% if 'input' in job_log or 'input' in step_errors %}

Input

{% if 'input' in job_log %} -

Log - - - -

-{% if 'input' in truncated_logs %} -Log too long to display. Download the full log -{% endif %} +

Log

{{ job_log['input'] }}
{% endif %} {% if 'input' in step_errors and step_errors['input'] is not none %} @@ -156,14 +149,7 @@

Error

{% if 'main' in job_log or 'main' in step_errors %}

Main

{% if 'main' in job_log %} -

Log - - - -

-{% if 'main' in truncated_logs %} -Log too long to display. Download the full log -{% endif %} +

Log

{{ job_log['main'] }}
{% endif %} {% if 'main' in step_errors and step_errors['main'] is not none %} @@ -175,14 +161,7 @@

Error

{% if 'output' in job_log or 'output' in step_errors %}

Output

{% if 'output' in job_log %} -

Log - - - -

-{% if 'output' in truncated_logs %} -Log too long to display. Download the full log -{% endif %} +

Log

{{ job_log['output'] }}
{% endif %} {% if 'output' in step_errors and step_errors['output'] is not none %} From 14e002fd51ad56ac6aae8714870db975a18419fc Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 8 Aug 2023 12:30:24 -0400 Subject: [PATCH 084/180] [batch] billing manager needs to close its billing_client (#13387) --- batch/batch/cloud/gcp/driver/billing_manager.py | 6 +++++- batch/batch/cloud/gcp/driver/driver.py | 9 +++++---- batch/batch/cloud/gcp/driver/resource_manager.py | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/batch/batch/cloud/gcp/driver/billing_manager.py b/batch/batch/cloud/gcp/driver/billing_manager.py index 189d73a12f0..4c9c13699bc 100644 --- a/batch/batch/cloud/gcp/driver/billing_manager.py +++ b/batch/batch/cloud/gcp/driver/billing_manager.py @@ -12,7 +12,8 @@ class GCPBillingManager(CloudBillingManager): @staticmethod - async def create(db: Database, billing_client: aiogoogle.GoogleBillingClient, regions: List[str]): + async def create(db: Database, credentials_file: str, regions: List[str]): + billing_client = aiogoogle.GoogleBillingClient(credentials_file=credentials_file) product_versions_dict = await refresh_product_versions_from_db(db) bm = GCPBillingManager(db, product_versions_dict, billing_client, regions) await bm.refresh_resources() @@ -36,3 +37,6 @@ def __init__( async def refresh_resources_from_retail_prices(self): prices = [price async for price in fetch_prices(self.billing_client, self.regions, self.currency_code)] await self._refresh_resources_from_retail_prices(prices) + + async def close(self): + await self.billing_client.close() diff --git a/batch/batch/cloud/gcp/driver/driver.py b/batch/batch/cloud/gcp/driver/driver.py index ae506ed757f..075400bb774 100644 --- a/batch/batch/cloud/gcp/driver/driver.py +++ b/batch/batch/cloud/gcp/driver/driver.py @@ -63,10 +63,8 @@ async def create( rate_limit=RateLimit(10, 60), ) - billing_client = aiogoogle.GoogleBillingClient(credentials_file=credentials_file) - zone_monitor = await ZoneMonitor.create(compute_client, regions, zone) - billing_manager = await GCPBillingManager.create(db, billing_client, regions) + billing_manager = await GCPBillingManager.create(db, credentials_file, regions) inst_coll_manager = InstanceCollectionManager(db, machine_name_prefix, zone_monitor, region, regions) resource_manager = GCPResourceManager(project, compute_client, billing_manager) @@ -153,7 +151,10 @@ async def shutdown(self) -> None: try: await self.compute_client.close() finally: - await self.activity_logs_client.close() + try: + await self.activity_logs_client.close() + finally: + await self._billing_manager.close() async def process_activity_logs(self) -> None: async def _process_activity_log_events_since(mark): diff --git a/batch/batch/cloud/gcp/driver/resource_manager.py b/batch/batch/cloud/gcp/driver/resource_manager.py index 857c5eeaa1b..b144be3fd78 100644 --- a/batch/batch/cloud/gcp/driver/resource_manager.py +++ b/batch/batch/cloud/gcp/driver/resource_manager.py @@ -43,7 +43,7 @@ def __init__( self, project: str, compute_client: aiogoogle.GoogleComputeClient, # BORROWED - billing_manager: GCPBillingManager, + billing_manager: GCPBillingManager, # BORROWED ): self.compute_client = compute_client self.project = project From 18f09ac7863df0aaf7f4090b8a2ddca530d8e32e Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 8 Aug 2023 16:06:19 -0400 Subject: [PATCH 085/180] [ci] Remove unused step that adds billing project for benchmark (#13393) I think this didn't get cleaned up when we deleted the benchmark service. --- build.yaml | 62 ------------------------------------------------------ 1 file changed, 62 deletions(-) diff --git a/build.yaml b/build.yaml index 55f228d95ff..a35b5086dab 100644 --- a/build.yaml +++ b/build.yaml @@ -2250,68 +2250,6 @@ steps: - default_ns - hailgenetics_hailtop_image - deploy_batch - - kind: runImage - name: create_billing_projects - resources: - memory: standard - cpu: '0.25' - image: - valueFrom: hailgenetics_hailtop_image.image - script: | - set -ex - export HAIL_DEFAULT_NAMESPACE={{ default_ns.name }} - - # create billing projects and add users to them - cat > create-billing-projects.py < Date: Wed, 9 Aug 2023 16:35:01 -0400 Subject: [PATCH 086/180] [batch] Mitigate siwei bug by removing cache (#13399) Before open batches, the `n_jobs` of a batch was a constant known before any jobs were added. Moreover, we did not start scheduling jobs until all the jobs were added to the database. Therefore, it was always safe to assume that the final "bunch" of jobs in the database was the last "bunch" ergo it spanned from its `start_job_id` to the job with id `n_jobs` (nb: job ids are 1-indexed). When open batches were added, the `n_jobs` became a mutable value. Moreover, `n_jobs` includes jobs in bunches *which have not yet been added to the database*. In particular, suppose two clients are each submitting a bunch of size 10. Each client independently "reserves" 10 job slots by atomically incrementing `n_jobs` by ten. `n_jobs` is now 20. Further suppose that the first bunch is added to the database and begins scheduling before the second bunch is added to the database. In this case, when calculating the size of this bunch (for use in the bunch cache, and *only* in the bunch cache), we see that this is the last (and only) bunch in the database and assume that `n_jobs` is the last job id in this bunch. This is incorrect because `n_jobs` includes the not-yet-visible second bunch. --- batch/batch/spec_writer.py | 46 ++++---------------------------------- 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/batch/batch/spec_writer.py b/batch/batch/spec_writer.py index 952e7e87f97..0a0bb9c43a1 100644 --- a/batch/batch/spec_writer.py +++ b/batch/batch/spec_writer.py @@ -1,19 +1,10 @@ -import collections import logging -from typing import Dict, Literal, Tuple - -import sortedcontainers +from typing import Literal, Tuple from hailtop.utils import secret_alnum_string log = logging.getLogger('batch.spec_writer') -JOB_TOKEN_CACHE: Dict[int, sortedcontainers.SortedSet] = collections.defaultdict( - lambda: sortedcontainers.SortedSet(key=lambda t: t[1]) -) -JOB_TOKEN_CACHE_MAX_BATCHES = 100 -JOB_TOKEN_CACHE_MAX_BUNCHES_PER_BATCH = 100 - class SpecWriter: byteorder: Literal['little', 'big'] = 'little' @@ -38,49 +29,20 @@ def get_spec_file_offsets(offsets): @staticmethod async def get_token_start_id(db, batch_id, job_id) -> Tuple[str, int]: - in_batch_cache = JOB_TOKEN_CACHE[batch_id] - index = in_batch_cache.bisect_key_right(job_id) - 1 - assert index < len(in_batch_cache) - if index >= 0: - token, start, end = in_batch_cache[index] - if job_id in range(start, end): - return (token, start) - - token, start_job_id, end_job_id = await SpecWriter._get_token_start_id_and_end_id(db, batch_id, job_id) - - # It is least likely that old batches or early bunches in a given - # batch will be needed again - if len(JOB_TOKEN_CACHE) == JOB_TOKEN_CACHE_MAX_BATCHES: - JOB_TOKEN_CACHE.pop(min(JOB_TOKEN_CACHE.keys())) - elif len(JOB_TOKEN_CACHE[batch_id]) == JOB_TOKEN_CACHE_MAX_BUNCHES_PER_BATCH: - JOB_TOKEN_CACHE[batch_id].pop(0) - - JOB_TOKEN_CACHE[batch_id].add((token, start_job_id, end_job_id)) - - return (token, start_job_id) - - @staticmethod - async def _get_token_start_id_and_end_id(db, batch_id, job_id) -> Tuple[str, int, int]: bunch_record = await db.select_and_fetchone( ''' -SELECT -batch_bunches.start_job_id, -batch_bunches.token, -(SELECT start_job_id FROM batch_bunches WHERE batch_id = %s AND start_job_id > %s ORDER BY start_job_id LIMIT 1) AS next_start_job_id, -batches.n_jobs +SELECT batch_bunches.start_job_id, batch_bunches.token FROM batch_bunches -JOIN batches ON batches.id = batch_bunches.batch_id WHERE batch_bunches.batch_id = %s AND batch_bunches.start_job_id <= %s ORDER BY batch_bunches.start_job_id DESC LIMIT 1; ''', - (batch_id, job_id, batch_id, job_id), + (batch_id, job_id), 'get_token_start_id', ) token = bunch_record['token'] start_job_id = bunch_record['start_job_id'] - end_job_id = bunch_record['next_start_job_id'] or (bunch_record['n_jobs'] + 1) - return (token, start_job_id, end_job_id) + return (token, start_job_id) def __init__(self, file_store, batch_id): self.file_store = file_store From 0e93c74bbbfbb6df594aff83f33f1e7900229fac Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 9 Aug 2023 17:51:51 -0400 Subject: [PATCH 087/180] [ci] Pass developers to dev deploy branches (#13398) --- build.yaml | 2 ++ ci/ci/ci.py | 2 +- ci/ci/github.py | 14 +++++++++++--- gear/gear/auth.py | 1 + 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/build.yaml b/build.yaml index a35b5086dab..c833df2f6c7 100644 --- a/build.yaml +++ b/build.yaml @@ -2229,6 +2229,8 @@ steps: valueFrom: hailgenetics_hailtop_image.image script: | set -ex + + export HAIL_DEFAULT_NAMESPACE={{ default_ns.name }} {% for user in code.get("developers", []) %} {% if user['username'] != 'test-dev' %} hailctl auth create-user \ diff --git a/ci/ci/ci.py b/ci/ci/ci.py index eaa2aa7a0f5..249086a0b21 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -521,7 +521,7 @@ async def dev_deploy_branch(request: web.Request, userdata: UserData) -> web.Res log.info('dev deploy failed: ' + message, exc_info=True) raise web.HTTPBadRequest(text=message) from e - unwatched_branch = UnwatchedBranch(branch, sha, userdata, extra_config) + unwatched_branch = UnwatchedBranch(branch, sha, userdata, app['developers'], extra_config=extra_config) batch_client = app['batch_client'] diff --git a/ci/ci/github.py b/ci/ci/github.py index 8c2c9329178..a6fec2f9f4c 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -8,14 +8,14 @@ import secrets from enum import Enum from shlex import quote as shq -from typing import Dict, List, Optional, Set, Union +from typing import Any, Dict, List, Optional, Set, Union import aiohttp import gidgethub import prometheus_client as pc # type: ignore import zulip -from gear import Database +from gear import Database, UserData from hailtop.batch_client.aioclient import Batch from hailtop.config import get_deploy_config from hailtop.utils import RETRY_FUNCTION_SCRIPT, check_shell, check_shell_output @@ -995,7 +995,15 @@ def checkout_script(self): class UnwatchedBranch(Code): - def __init__(self, branch, sha, userdata, developers, extra_config=None): + def __init__( + self, + branch: FQBranch, + sha: str, + userdata: UserData, + developers: List[UserData], + *, + extra_config: Optional[Dict[str, Any]] = None, + ): self.branch = branch self.user = userdata['username'] self.namespace = userdata['namespace_name'] diff --git a/gear/gear/auth.py b/gear/gear/auth.py index c9b67c49ec3..23f7537aff6 100644 --- a/gear/gear/auth.py +++ b/gear/gear/auth.py @@ -25,6 +25,7 @@ class UserData(TypedDict): username: str + namespace_name: str is_developer: bool is_service_account: bool hail_credentials_secret_name: str From 4d9e50cf69c77e0bf2d63ce40bf8202d24cf25e1 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 9 Aug 2023 19:00:15 -0400 Subject: [PATCH 088/180] [hailctl] Add basic tests for hailctl config (#13389) This is pretty bare bones but I thought this might help a lot with the testing of all your upcoming `hailctl config` changes rather than having to manually test various possible combinations. Run by just invoking pytest: `pytest hail/python/test/hailtop/hailctl/config` --- hail/python/hailtop/config/user_config.py | 9 +-- .../test/hailtop/hailctl/config/conftest.py | 15 +++++ .../test/hailtop/hailctl/config/test_cli.py | 61 +++++++++++++++++++ hail/scripts/test_requester_pays_parsing.py | 7 +-- 4 files changed, 78 insertions(+), 14 deletions(-) create mode 100644 hail/python/test/hailtop/hailctl/config/conftest.py create mode 100644 hail/python/test/hailtop/hailctl/config/test_cli.py diff --git a/hail/python/hailtop/config/user_config.py b/hail/python/hailtop/config/user_config.py index 92504ec2011..b54c075931b 100644 --- a/hail/python/hailtop/config/user_config.py +++ b/hail/python/hailtop/config/user_config.py @@ -19,8 +19,7 @@ def get_user_config_path() -> Path: return Path(xdg_config_home(), 'hail', 'config.ini') -def _load_user_config(): - global user_config +def get_user_config() -> configparser.ConfigParser: user_config = configparser.ConfigParser() config_file = get_user_config_path() # in older versions, the config file was accidentally named @@ -30,12 +29,6 @@ def _load_user_config(): if old_path.exists() and not config_file.exists(): old_path.rename(config_file) user_config.read(config_file) - - -def get_user_config() -> configparser.ConfigParser: - if user_config is None: - _load_user_config() - assert user_config is not None return user_config diff --git a/hail/python/test/hailtop/hailctl/config/conftest.py b/hail/python/test/hailtop/hailctl/config/conftest.py new file mode 100644 index 00000000000..95ca40e0f4d --- /dev/null +++ b/hail/python/test/hailtop/hailctl/config/conftest.py @@ -0,0 +1,15 @@ +import pytest +import tempfile + +from typer.testing import CliRunner + + +@pytest.fixture() +def config_dir(): + with tempfile.TemporaryDirectory() as d: + yield d + + +@pytest.fixture +def runner(config_dir): + yield CliRunner(mix_stderr=False, env={'XDG_CONFIG_HOME': config_dir}) diff --git a/hail/python/test/hailtop/hailctl/config/test_cli.py b/hail/python/test/hailtop/hailctl/config/test_cli.py new file mode 100644 index 00000000000..d5f07937d61 --- /dev/null +++ b/hail/python/test/hailtop/hailctl/config/test_cli.py @@ -0,0 +1,61 @@ +import pytest + +from typer.testing import CliRunner + +from hailtop.hailctl.config import cli + + +def test_config_location(runner: CliRunner, config_dir: str): + res = runner.invoke(cli.app, 'config-location', catch_exceptions=False) + assert res.exit_code == 0 + assert res.stdout.strip() == f'{config_dir}/hail/config.ini' + + +def test_config_list_empty_config(runner: CliRunner): + res = runner.invoke(cli.app, 'list', catch_exceptions=False) + assert res.exit_code == 0 + assert res.stdout.strip() == '' + + +@pytest.mark.parametrize( + 'name,value', + [ + ('batch/backend', 'batch'), + ('batch/billing_project', 'test'), + ('batch/remote_tmpdir', 'gs://foo/bar'), + ('query/backend', 'spark'), + + # hailctl currently accepts arbitrary settings + ('foo/bar', 'baz'), + ], +) +def test_config_set(name: str, value: str, runner: CliRunner): + runner.invoke(cli.app, ['set', name, value], catch_exceptions=False) + + res = runner.invoke(cli.app, 'list', catch_exceptions=False) + assert res.exit_code == 0 + assert res.stdout.strip() == f'{name}={value}' + + res = runner.invoke(cli.app, ['get', name], catch_exceptions=False) + assert res.exit_code == 0 + assert res.stdout.strip() == value + + +def test_config_get_bad_names(runner: CliRunner): + res = runner.invoke(cli.app, ['get', 'foo'], catch_exceptions=False) + assert res.exit_code == 0 + assert res.stdout.strip() == '' + + res = runner.invoke(cli.app, ['get', '/a/b/c'], catch_exceptions=False) + assert res.exit_code == 1 + + +@pytest.mark.parametrize( + 'name,value', + [ + ('batch/remote_tmpdir', 'asdf://foo/bar'), + ], +) +def test_config_set_bad_value(name: str, value: str, runner: CliRunner): + res = runner.invoke(cli.app, ['set', name, value], catch_exceptions=False) + assert res.exit_code == 1 diff --git a/hail/scripts/test_requester_pays_parsing.py b/hail/scripts/test_requester_pays_parsing.py index 5a4e621fc1b..4bdc9c2a6a2 100644 --- a/hail/scripts/test_requester_pays_parsing.py +++ b/hail/scripts/test_requester_pays_parsing.py @@ -5,7 +5,7 @@ from hailtop.aiocloud.aiogoogle import get_gcs_requester_pays_configuration from hailtop.aiocloud.aiogoogle.user_config import spark_conf_path, get_spark_conf_gcs_requester_pays_configuration from hailtop.utils.process import check_exec_output -from hailtop.config.user_config import configuration_of, _load_user_config +from hailtop.config.user_config import configuration_of if 'YOU_MAY_OVERWRITE_MY_SPARK_DEFAULTS_CONF_AND_HAILCTL_SETTINGS' not in os.environ: @@ -29,7 +29,6 @@ async def unset_hailctl(): 'unset', 'gcs_requester_pays/buckets', ) - _load_user_config() # force reload of user config @pytest.mark.asyncio @@ -140,8 +139,6 @@ async def test_hailctl_takes_precedence_1(): echo=True ) - _load_user_config() # force reload of user config - actual = get_gcs_requester_pays_configuration() assert actual == 'hailctl_project', str(( configuration_of('gcs_requester_pays', 'project', None, None), @@ -178,7 +175,5 @@ async def test_hailctl_takes_precedence_2(): echo=True ) - _load_user_config() # force reload of user config - actual = get_gcs_requester_pays_configuration() assert actual == ('hailctl_project2', ['bucket1', 'bucket2']) From 364e300d9ea57ac48f497d0209951f2536904f59 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 9 Aug 2023 22:14:32 -0400 Subject: [PATCH 089/180] [batch] Dont wait on a network namespace forever (#13403) A mitigation, but not resolution, for #13402, this errors a job after 10 seconds of waiting on a network namespace, as it should never take that long to create one. --- batch/batch/worker/worker.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index aef542c3b2c..a7daa680b03 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -1026,11 +1026,12 @@ async def _setup_overlay(self): async def _setup_network_namespace(self): assert network_allocator assert port_allocator - if self.network == 'private': - self.netns = await network_allocator.allocate_private() - else: - assert self.network is None or self.network == 'public' - self.netns = await network_allocator.allocate_public() + async with async_timeout.timeout(10): + if self.network == 'private': + self.netns = await network_allocator.allocate_private() + else: + assert self.network is None or self.network == 'public' + self.netns = await network_allocator.allocate_public() if self.port is not None: self.host_port = await port_allocator.allocate() From c46f0ffdb1af398936c1eec9b8565247fb86cd3c Mon Sep 17 00:00:00 2001 From: Dan King Date: Wed, 9 Aug 2023 23:48:03 -0400 Subject: [PATCH 090/180] [batch] expose Job.spot (#13396) Folks need this when preemption rates are too high for their jobs. cc: @daniel-goldstein --------- Co-authored-by: jigold --- batch/utils/stress.py | 2 +- hail/python/hailtop/batch/batch.py | 10 ++++ hail/python/hailtop/batch/job.py | 26 +++++++++++ hail/python/test/hailtop/batch/test_batch.py | 48 ++++++++++++++++++-- 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/batch/utils/stress.py b/batch/utils/stress.py index 8cd1528c566..e616daaf13e 100644 --- a/batch/utils/stress.py +++ b/batch/utils/stress.py @@ -30,7 +30,7 @@ def stress(): if flip(0.01): c._machine_type = 'n1-standard-1' if flip(0.5): - c._preemptible = False + c.spot(False) b.run(open=False, wait=False) diff --git a/hail/python/hailtop/batch/batch.py b/hail/python/hailtop/batch/batch.py index 38f11b165d2..e4d63eac114 100644 --- a/hail/python/hailtop/batch/batch.py +++ b/hail/python/hailtop/batch/batch.py @@ -86,6 +86,10 @@ class Batch: the `dill` Python package installed and have the same version of Python installed that is currently running. If `None`, a compatible Python image with `dill` pre-installed will automatically be used if the current Python version is 3.9, or 3.10. + default_spot: + If unspecified or ``True``, jobs will run by default on spot instances. If ``False``, jobs + will run by default on non-spot instances. Each job can override this setting with + :meth:`.Job.spot`. project: DEPRECATED: please specify `google_project` on the ServiceBackend instead. If specified, the project to use when authenticating with Google Storage. Google Storage is used to @@ -150,6 +154,7 @@ def __init__(self, default_timeout: Optional[Union[float, int]] = None, default_shell: Optional[str] = None, default_python_image: Optional[str] = None, + default_spot: Optional[bool] = None, project: Optional[str] = None, cancel_after_n_failures: Optional[int] = None): self._jobs: List[job.Job] = [] @@ -186,6 +191,7 @@ def __init__(self, self._default_timeout = default_timeout self._default_shell = default_shell self._default_python_image = default_python_image + self._default_spot = default_spot if project is not None: warnings.warn( @@ -310,6 +316,8 @@ def new_bash_job(self, j.storage(self._default_storage) if self._default_timeout is not None: j.timeout(self._default_timeout) + if self._default_spot is not None: + j.spot(self._default_spot) if isinstance(self._backend, _backend.ServiceBackend): j.regions(self._backend.regions) @@ -382,6 +390,8 @@ def hello(name): j.storage(self._default_storage) if self._default_timeout is not None: j.timeout(self._default_timeout) + if self._default_spot is not None: + j.spot(self._default_spot) if isinstance(self._backend, _backend.ServiceBackend): j.regions(self._backend.regions) diff --git a/hail/python/hailtop/batch/job.py b/hail/python/hailtop/batch/job.py index c6e8b1d7d3b..ce5e914db47 100644 --- a/hail/python/hailtop/batch/job.py +++ b/hail/python/hailtop/batch/job.py @@ -342,6 +342,32 @@ def always_run(self, always_run: bool = True) -> 'Job': self._always_run = always_run return self + def spot(self, is_spot: bool) -> 'Job': + """ + Set whether a job is run on spot instances. By default, all jobs run on spot instances. + + Examples + -------- + + Ensure a job only runs on non-spot instances: + + >>> b = Batch(backend=backend.ServiceBackend('test')) + >>> j = b.new_job() + >>> j = j.spot(False) + >>> j = j.command(f'echo "hello"') + + Parameters + ---------- + is_spot: + If False, this job will be run on non-spot instances. + + Returns + ------- + Same job object. + """ + self._preemptible = is_spot + return self + def regions(self, regions: Optional[List[str]]) -> 'Job': """ Set the cloud regions a job can run in. diff --git a/hail/python/test/hailtop/batch/test_batch.py b/hail/python/test/hailtop/batch/test_batch.py index a013c20b8cd..503106a1ee0 100644 --- a/hail/python/test/hailtop/batch/test_batch.py +++ b/hail/python/test/hailtop/batch/test_batch.py @@ -525,16 +525,13 @@ def sync_exists(self, url): def sync_write(self, url, data): return async_to_blocking(self.router_fs.write(url, data)) - def batch(self, requester_pays_project=None, default_python_image=None, - cancel_after_n_failures=None): + def batch(self, **kwargs): name_of_test_method = inspect.stack()[1][3] return Batch(name=name_of_test_method, backend=self.backend, default_image=DOCKER_ROOT_IMAGE, attributes={'foo': 'a', 'bar': 'b'}, - requester_pays_project=requester_pays_project, - default_python_image=default_python_image, - cancel_after_n_failures=cancel_after_n_failures) + **kwargs) def test_single_task_no_io(self): b = self.batch() @@ -1319,3 +1316,44 @@ def test_wait_on_empty_batch_update(self): b = self.batch() b.run(wait=True) b.run(wait=True) + + def test_non_spot_job(self): + b = self.batch() + j = b.new_job() + j.spot(False) + j.command('echo hello') + res = b.run() + assert res is not None + assert res.get_job(1).status()['spec']['resources']['preemptible'] == False + + def test_spot_unspecified_job(self): + b = self.batch() + j = b.new_job() + j.command('echo hello') + res = b.run() + assert res is not None + assert res.get_job(1).status()['spec']['resources']['preemptible'] == True + + def test_spot_true_job(self): + b = self.batch() + j = b.new_job() + j.spot(True) + j.command('echo hello') + res = b.run() + assert res is not None + assert res.get_job(1).status()['spec']['resources']['preemptible'] == True + + def test_non_spot_batch(self): + b = self.batch(default_spot=False) + j1 = b.new_job() + j1.command('echo hello') + j2 = b.new_job() + j2.command('echo hello') + j3 = b.new_job() + j3.spot(True) + j3.command('echo hello') + res = b.run() + assert res is not None + assert res.get_job(1).status()['spec']['resources']['preemptible'] == False + assert res.get_job(2).status()['spec']['resources']['preemptible'] == False + assert res.get_job(3).status()['spec']['resources']['preemptible'] == True From cd952f1135c2fbf0087fc6f5db867b3b99f10467 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 10 Aug 2023 11:46:12 -0400 Subject: [PATCH 091/180] [ci] Point to batch job page instead of CI job page (#13406) Not really any point in a custom CI job page that we have to maintain parallel to the batch job page. --- ci/ci/ci.py | 17 -------- ci/ci/templates/job-table.html | 2 +- ci/ci/templates/job.html | 77 ---------------------------------- 3 files changed, 1 insertion(+), 95 deletions(-) delete mode 100644 ci/ci/templates/job.html diff --git a/ci/ci/ci.py b/ci/ci/ci.py index 249086a0b21..77bda23ba2e 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -268,23 +268,6 @@ def get_maybe_wb_for_batch(b: Batch): return None -@routes.get('/batches/{batch_id}/jobs/{job_id}') -@auth.web_authenticated_developers_only() -async def get_job(request, userdata): - batch_id = int(request.match_info['batch_id']) - job_id = int(request.match_info['job_id']) - batch_client = request.app['batch_client'] - job = await batch_client.get_job(batch_id, job_id) - page_context = { - 'batch_id': batch_id, - 'job_id': job_id, - 'job_log': await job.log(), - 'job_status': json.dumps(await job.status(), indent=2), - 'attempts': await job.attempts(), - } - return await render_template('ci', request, userdata, 'job.html', page_context) - - def filter_wbs(wbs: List[WatchedBranchConfig], pred: Callable[[PRConfig], bool]): return [{**wb, 'prs': [pr for pr in wb['prs'] if pred(pr)]} for wb in wbs] diff --git a/ci/ci/templates/job-table.html b/ci/ci/templates/job-table.html index e50ebf9ef87..ca7b2dcf2d9 100644 --- a/ci/ci/templates/job-table.html +++ b/ci/ci/templates/job-table.html @@ -18,7 +18,7 @@ {% for job in jobs %} - {{ job['job_id'] }} + {{ job['job_id'] }} {{ job['name'] }} {{ job['state'] }} diff --git a/ci/ci/templates/job.html b/ci/ci/templates/job.html deleted file mode 100644 index c86e8315d02..00000000000 --- a/ci/ci/templates/job.html +++ /dev/null @@ -1,77 +0,0 @@ -{% extends "layout.html" %} -{% block title %}Batch {{ batch_id }} Job {{ job_id }}{% endblock %} -{% block content %} -

Batch {{ batch_id }} Job {{ job_id }}

- -
- -
- -

Attempts

- {% if attempts %} - - - - - - - - - - - - - {% for attempt in attempts %} - - - - - - - - - {% endfor %} - -
Attempt IDInstanceStartEndDurationReason
{{ attempt['attempt_id'] }}{{ attempt['instance_name'] }} - {% if 'start_time' in attempt and attempt['start_time'] is not none %} - {{ attempt['start_time'] }} - {% endif %} - - {% if 'end_time' in attempt and attempt['end_time'] is not none %} - {{ attempt['end_time'] }} - {% endif %} - - {% if 'duration' in attempt and attempt['duration'] is not none %} - {{ attempt['duration'] }} - {% endif %} - - {% if 'reason' in attempt and attempt['reason'] is not none %} - {{ attempt['reason'] }} - {% endif %} -
- {% else %} -

No attempts

- {% endif %} - - {% if job_log %} -

Log

- - {% if 'input' in job_log %} -

Input

-
{{ job_log['input'] }}
- {% endif %} - - {% if 'main' in job_log %} -

Main

-
{{ job_log['main'] }}
- {% endif %} - - {% if 'output' in job_log %} -

Output

-
{{ job_log['output'] }}
- {% endif %} - {% endif %} - -

Status

-
{{ job_status }}
-{% endblock %} From fef71e1bb3a59260d157affc153b487c68315491 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 10 Aug 2023 13:05:15 -0400 Subject: [PATCH 092/180] [batch] Fix bitrot in VM image creation script (#13404) Did a few things here: - Specifying a namespace is necessary to run the script, and must be supplied as `default` if you want to change the production images - Explicitly specify the `subnet` in the VM creation. This was optional before but BITS changed some settings in GCP such that you *have* to specify subnets when creating a VM. - I hard-coded the ubuntu image. I think this is better for reproducibility/auditing, but this actually broke because the `gcloud` query that used to return one image now returns two (they added an ARM ubuntu). --- batch/gcp-create-worker-image.sh | 37 +++++++++++++++++++++----------- devbin/functions.sh | 6 +----- infra/gcp/README.md | 2 +- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/batch/gcp-create-worker-image.sh b/batch/gcp-create-worker-image.sh index 586092ed964..5226a5e73e9 100755 --- a/batch/gcp-create-worker-image.sh +++ b/batch/gcp-create-worker-image.sh @@ -2,14 +2,29 @@ set -e -source $HAIL/devbin/functions.sh +cd "$(dirname "$0")" +source ../devbin/functions.sh -PROJECT=$(get_global_config_field gcp_project) -ZONE=$(get_global_config_field gcp_zone) -DOCKER_ROOT_IMAGE=$(get_global_config_field docker_root_image) +if [ -z "${NAMESPACE}" ]; then + echo "Must specify a NAMESPACE environment variable" + exit 1; +fi + +PROJECT=$(get_global_config_field gcp_project $NAMESPACE) +ZONE=$(get_global_config_field gcp_zone $NAMESPACE) +DOCKER_ROOT_IMAGE=$(get_global_config_field docker_root_image $NAMESPACE) WORKER_IMAGE_VERSION=12 -BUILDER=build-batch-worker-image + +if [ "$NAMESPACE" == "default" ]; then + WORKER_IMAGE=batch-worker-${WORKER_IMAGE_VERSION} + BUILDER=build-batch-worker-image +else + WORKER_IMAGE=batch-worker-$NAMESPACE-${WORKER_IMAGE_VERSION} + BUILDER=build-batch-worker-$NAMESPACE-image +fi + +UBUNTU_IMAGE=ubuntu-minimal-2004-focal-v20230725 create_build_image_instance() { gcloud -q compute --project ${PROJECT} instances delete \ @@ -18,16 +33,12 @@ create_build_image_instance() { python3 ../ci/jinja2_render.py '{"global":{"docker_root_image":"'${DOCKER_ROOT_IMAGE}'"}}' \ build-batch-worker-image-startup-gcp.sh build-batch-worker-image-startup-gcp.sh.out - UBUNTU_IMAGE=$(gcloud compute images list \ - --standard-images \ - --filter 'family="ubuntu-minimal-2004-lts"' \ - --format='value(name)') - gcloud -q compute instances create ${BUILDER} \ --project ${PROJECT} \ --zone=${ZONE} \ --machine-type=n1-standard-1 \ --network=default \ + --subnet=default \ --network-tier=PREMIUM \ --metadata-from-file startup-script=build-batch-worker-image-startup-gcp.sh.out \ --no-restart-on-failure \ @@ -40,10 +51,10 @@ create_build_image_instance() { } create_worker_image() { - gcloud -q compute images delete batch-worker-${WORKER_IMAGE_VERSION} \ + gcloud -q compute images delete $WORKER_IMAGE \ --project ${PROJECT} || true - gcloud -q compute images create batch-worker-${WORKER_IMAGE_VERSION} \ + gcloud -q compute images create $WORKER_IMAGE \ --project ${PROJECT} \ --source-disk-zone=${ZONE} \ --source-disk=${BUILDER} @@ -63,4 +74,4 @@ main() { create_worker_image } -confirm "Building image with properties:\n Version: ${WORKER_IMAGE_VERSION}\n Project: ${PROJECT}\n Zone: ${ZONE}" && main +confirm "Building image $WORKER_IMAGE with properties:\n Version: ${WORKER_IMAGE_VERSION}\n Project: ${PROJECT}\n Zone: ${ZONE}" && main diff --git a/devbin/functions.sh b/devbin/functions.sh index 3deabdcaf34..c90171506d5 100644 --- a/devbin/functions.sh +++ b/devbin/functions.sh @@ -197,7 +197,7 @@ download-configmap() { } get_global_config_field() { - kubectl get secret global-config --template={{.data.$1}} | base64 --decode + kubectl -n ${2:-default} get secret global-config --template={{.data.$1}} | base64 --decode } gcpsetcluster() { @@ -237,10 +237,6 @@ azsshworker() { ssh -i ~/.ssh/batch_worker_ssh_rsa batch-worker@$worker_ip } -get_global_config_field() { - kubectl get secret global-config --template={{.data.$1}} | base64 --decode -} - confirm() { printf "$1\n" read -r -p "Are you sure? [y/N] " response diff --git a/infra/gcp/README.md b/infra/gcp/README.md index f36a68a133d..69930f5a010 100644 --- a/infra/gcp/README.md +++ b/infra/gcp/README.md @@ -246,7 +246,7 @@ You can now install Hail: - Create the batch worker VM image. Run: ``` - $HAIL/batch/gcp-create-worker-image.sh + NAMESPACE=default $HAIL/batch/gcp-create-worker-image.sh ``` - Download the global-config to be used by `bootstrap.py`. From c1e6bcc3a291db1cfe8f37434e5f9210331a125f Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 10 Aug 2023 14:15:11 -0400 Subject: [PATCH 093/180] [build.yaml] logging in create_accounts step (#13394) --- ci/bootstrap_create_accounts.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/ci/bootstrap_create_accounts.py b/ci/bootstrap_create_accounts.py index 049a9539aee..abece32ada8 100644 --- a/ci/bootstrap_create_accounts.py +++ b/ci/bootstrap_create_accounts.py @@ -1,15 +1,19 @@ -import base64 -import json -import os - -import kubernetes_asyncio.client -import kubernetes_asyncio.config - -from auth.driver.driver import create_user -from gear import Database, transaction -from gear.clients import get_identity_client -from gear.cloud_config import get_global_config -from hailtop.utils import async_to_blocking +from hailtop.hail_logging import configure_logging + +configure_logging() + +import base64 # noqa: E402 pylint: disable=wrong-import-position +import json # noqa: E402 pylint: disable=wrong-import-position +import os # noqa: E402 pylint: disable=wrong-import-position + +import kubernetes_asyncio.client # noqa: E402 pylint: disable=wrong-import-position +import kubernetes_asyncio.config # noqa: E402 pylint: disable=wrong-import-position + +from auth.driver.driver import create_user # noqa: E402 pylint: disable=wrong-import-position +from gear import Database, transaction # noqa: E402 pylint: disable=wrong-import-position +from gear.clients import get_identity_client # noqa: E402 pylint: disable=wrong-import-position +from gear.cloud_config import get_global_config # noqa: E402 pylint: disable=wrong-import-position +from hailtop.utils import async_to_blocking # noqa: E402 pylint: disable=wrong-import-position,ungrouped-imports CLOUD = get_global_config()['cloud'] SCOPE = os.environ['HAIL_SCOPE'] From bd4134f1da3b3cfa01446f8ca59755dce4ff2e33 Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 10 Aug 2023 15:26:14 -0400 Subject: [PATCH 094/180] [build.yaml] scale dev namespaces to zero 9p-9a weekdays and weekends (#13397) cc: @jigold @iris-garden @sjparsa , since you all use dev namespaces. --------- Co-authored-by: Daniel Goldstein --- build.yaml | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/build.yaml b/build.yaml index c833df2f6c7..f87458be6ce 100644 --- a/build.yaml +++ b/build.yaml @@ -3681,3 +3681,78 @@ steps: - test_hail_python_service_backend_gcp - test_hail_python_service_backend_azure - cancel_all_running_test_batches + - kind: runImage + name: setup_dev_namespace_autoscalers + resources: + memory: standard + cpu: '0.25' + image: + valueFrom: ci_utils_image.image + script: | + set -ex + cat > dev-namespace-scalers.yaml <<'EOF' + {% for user in code.get("developers", []) %} + {% if user['username'] != 'test-dev' %} + apiVersion: batch/v1 + kind: CronJob + metadata: + name: dev-namespace-scaledown-{{ user["username"] }} + namespace: {{ user["username"] }} + spec: + schedule: 0 20 * * 1,2,3,4,5" # Weekdays at 8p + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 1 + failedJobsHistoryLimit: 1 + jobTemplate: + spec: + template: + spec: + serviceAccountName: admin + containers: + - name: dev-namespace-scaledown-dking + image: bitnami/kubectl:latest + command: + - /bin/sh + - -c + - set -ex ; kubectl scale deployments --all -n {{ user["username"] }} --replicas=0 && kubectl scale statefulsets --all -n {{ user["username"] }} --replicas=0 + restartPolicy: OnFailure + --- + apiVersion: batch/v1 + kind: CronJob + metadata: + name: dev-namespace-scaleup-{{ user["username"] }} + namespace: {{ user["username"] }} + spec: + schedule: "0 9 * * 1,2,3,4,5" # Weekdays at 9a + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 0 + failedJobsHistoryLimit: 1 + jobTemplate: + spec: + template: + spec: + serviceAccountName: admin + containers: + - name: dev-namespace-daytime-autoscaler + image: bitnami/kubectl:latest + command: + - /bin/sh + - -c + - set -ex ; kubectl scale deployments --all -n {{ user["username"] }} --replicas=1 && kubectl scale statefulsets --all -n {{ user["username"] }} --replicas=1 + restartPolicy: OnFailure + --- + {% endif %} + {% endfor %} + EOF + kubectl apply -f dev-namespace-scalers.yaml + scopes: + - deploy + serviceAccount: + name: admin + namespace: + valueFrom: default_ns.name + dependsOn: + - ci_utils_image + - default_ns + scopes: + - deploy From 35d6a6424028c02ea225e75e565324c65ebb9979 Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 10 Aug 2023 16:46:58 -0400 Subject: [PATCH 095/180] [batch] add missing types and deduplicate code (#13401) I ran into missing type information while I was writing the tests in https://github.com/hail-is/hail/pull/13400 --- hail/python/hailtop/batch_client/aioclient.py | 48 +++++++++++++------ hail/python/hailtop/batch_client/client.py | 31 ++---------- hail/python/hailtop/utils/__init__.py | 3 +- hail/python/hailtop/utils/utils.py | 10 +++- 4 files changed, 47 insertions(+), 45 deletions(-) diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index 631eca09a8d..33dc40eddd2 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -360,14 +360,14 @@ class Batch: def __init__(self, client: 'BatchClient', id: int, - attributes: Dict[str, str], + attributes: Optional[Dict[str, str]], token: str, *, - last_known_status: Optional[bool] = None, + last_known_status: Optional[Dict[str, Any]] = None, submission_info: Optional[BatchSubmissionInfo] = None): self._client = client self.id: int = id - self.attributes = attributes + self.attributes: Dict[str, str] = attributes or {} self.token = token self._last_known_status = last_known_status self.submission_info = submission_info or BatchSubmissionInfo() @@ -420,17 +420,24 @@ async def get_job_log(self, job_id: int) -> Optional[Dict[str, Any]]: # msec_mcpu: int # cost: float # } - async def status(self): + async def status(self) -> Dict[str, Any]: resp = await self._client._get(f'/api/v1alpha/batches/{self.id}') - self._last_known_status = await resp.json() + json_status = await resp.json() + assert isinstance(json_status, dict), json_status + self._last_known_status = json_status return self._last_known_status - async def last_known_status(self): + async def last_known_status(self) -> Dict[str, Any]: if self._last_known_status is None: return await self.status() # updates _last_known_status return self._last_known_status - async def _wait(self, description: str, progress: BatchProgressBar, disable_progress_bar: bool, starting_job: int): + async def _wait(self, + description: str, + progress: BatchProgressBar, + disable_progress_bar: bool, + starting_job: int + ) -> Dict[str, Any]: deploy_config = get_deploy_config() url = deploy_config.external_url('batch', f'/batches/{self.id}') i = 0 @@ -460,7 +467,7 @@ async def wait(self, description: str = '', progress: Optional[BatchProgressBar] = None, starting_job: int = 1, - ): + ) -> Dict[str, Any]: if description: description += ': ' if progress is not None: @@ -486,20 +493,28 @@ async def delete(self): class BatchBuilder: - def __init__(self, client, *, attributes=None, callback=None, token=None, cancel_after_n_failures=None, batch=None): + def __init__(self, + client: 'BatchClient', + *, + attributes: Optional[Dict[str, str]] = None, + callback: Optional[str] = None, + token: Optional[str] = None, + cancel_after_n_failures: Optional[int] = None, + batch: Optional[Batch] = None + ): self._client = client self._job_idx = 0 - self._job_specs = [] - self._jobs = [] - self._batch: Optional[Batch] = batch + self._job_specs: List[Dict[str, Any]] = [] + self._jobs: List[Job] = [] + self._batch = batch self.attributes = attributes self.callback = callback if token is None: token = secrets.token_urlsafe(32) - self.token = token + self.token: str = token - self._update_id = None + self._update_id: Optional[int] = None self._cancel_after_n_failures = cancel_after_n_failures @@ -943,9 +958,12 @@ async def get_job_attempts(self, batch_id, job_id): async def get_batch(self, id) -> Batch: b_resp = await self._get(f'/api/v1alpha/batches/{id}') b = await b_resp.json() + assert isinstance(b, dict), b + attributes = b.get('attributes') + assert attributes is None or isinstance(attributes, dict), attributes return Batch(self, b['id'], - attributes=b.get('attributes'), + attributes=attributes, token=b['token'], last_known_status=b) diff --git a/hail/python/hailtop/batch_client/client.py b/hail/python/hailtop/batch_client/client.py index 11027e95b87..61a13a4c329 100644 --- a/hail/python/hailtop/batch_client/client.py +++ b/hail/python/hailtop/batch_client/client.py @@ -1,36 +1,11 @@ from typing import Any, Dict, List, Optional, Union -import asyncio -import contextlib +from hailtop.utils import async_to_blocking, ait_to_blocking from ..config import DeployConfig from . import aioclient from .. import httpx -def async_to_blocking(coro): - loop = asyncio.get_event_loop() - task = asyncio.ensure_future(coro) - try: - return loop.run_until_complete(task) - finally: - if not task.done(): - task.cancel() - with contextlib.suppress(asyncio.CancelledError): - loop.run_until_complete(task) - - -def sync_anext(ait): - return async_to_blocking(ait.__anext__()) - - -def agen_to_blocking(agen): - while True: - try: - yield sync_anext(agen) - except StopAsyncIteration: - break - - class Job: @staticmethod def _get_error(job_status, task): @@ -185,7 +160,7 @@ def last_known_status(self): return async_to_blocking(self._async_batch.last_known_status()) def jobs(self, q=None, version=None): - return agen_to_blocking(self._async_batch.jobs(q=q, version=version)) + return ait_to_blocking(self._async_batch.jobs(q=q, version=version)) def get_job(self, job_id: int) -> Job: j = async_to_blocking(self._async_batch.get_job(job_id)) @@ -305,7 +280,7 @@ def reset_billing_project(self, billing_project): self._async_client.reset_billing_project(billing_project) def list_batches(self, q=None, last_batch_id=None, limit=2**64, version=None): - for b in agen_to_blocking(self._async_client.list_batches(q=q, last_batch_id=last_batch_id, limit=limit, version=version)): + for b in ait_to_blocking(self._async_client.list_batches(q=q, last_batch_id=last_batch_id, limit=limit, version=version)): yield Batch.from_async_batch(b) def get_job(self, batch_id, job_id): diff --git a/hail/python/hailtop/utils/__init__.py b/hail/python/hailtop/utils/__init__.py index 35e18fafc89..0b8807f2505 100644 --- a/hail/python/hailtop/utils/__init__.py +++ b/hail/python/hailtop/utils/__init__.py @@ -15,7 +15,7 @@ unpack_comma_delimited_inputs, unpack_key_value_inputs, retry_all_errors_n_times, Timings, is_limited_retries_error, am_i_interactive, is_delayed_warning_error, retry_transient_errors_with_delayed_warnings, - periodically_call_with_dynamic_sleep, delay_ms_for_try) + periodically_call_with_dynamic_sleep, delay_ms_for_try, ait_to_blocking) from .process import ( CalledProcessError, check_shell, check_shell_output, check_exec_output, sync_check_shell, sync_check_shell_output, sync_check_exec) @@ -34,6 +34,7 @@ 'flatten', 'filter_none', 'async_to_blocking', + 'ait_to_blocking', 'blocking_to_async', 'AsyncWorkerPool', 'CalledProcessError', diff --git a/hail/python/hailtop/utils/utils.py b/hail/python/hailtop/utils/utils.py index 0587812ac8a..57e78b7a35a 100644 --- a/hail/python/hailtop/utils/utils.py +++ b/hail/python/hailtop/utils/utils.py @@ -1,5 +1,5 @@ from typing import (Any, Callable, TypeVar, Awaitable, Mapping, Optional, Type, List, Dict, Iterable, Tuple, - Generic, cast) + Generic, cast, AsyncIterator, Iterator) from typing import Literal from types import TracebackType import concurrent @@ -155,6 +155,14 @@ def async_to_blocking(coro: Awaitable[T]) -> T: loop.run_until_complete(task) +def ait_to_blocking(ait: AsyncIterator[T]) -> Iterator[T]: + while True: + try: + yield async_to_blocking(ait.__anext__()) + except StopAsyncIteration: + break + + async def blocking_to_async(thread_pool: concurrent.futures.Executor, fun: Callable[..., T], *args, From 6f79d0c5857fb786d25060bee926d2073cc869ab Mon Sep 17 00:00:00 2001 From: jigold Date: Thu, 10 Aug 2023 18:04:05 -0400 Subject: [PATCH 096/180] [batch] Use new v3 billing tables on the driver and front end (#13408) Let's use the new compacted billing tables! --- batch/batch/driver/main.py | 2 +- batch/batch/front_end/front_end.py | 6 +++--- batch/batch/utils.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 4bbae3e572e..5644abbe24e 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -1162,7 +1162,7 @@ async def check(tx): SELECT billing_project, JSON_OBJECTAGG(resource, `usage`) as resources FROM ( SELECT billing_project, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM aggregated_billing_project_user_resources_v2 + FROM aggregated_billing_project_user_resources_v3 GROUP BY billing_project, resource_id) AS t LEFT JOIN resources ON t.resource_id = resources.resource_id GROUP BY t.billing_project diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index e58caf65c86..c62ff417579 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -1267,7 +1267,7 @@ async def insert(tx): SELECT COALESCE(SUM(t.`usage` * rate), 0) AS cost FROM ( SELECT resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM aggregated_billing_project_user_resources_v2 + FROM aggregated_billing_project_user_resources_v3 WHERE billing_project = %s GROUP BY resource_id ) AS t @@ -2330,8 +2330,8 @@ async def parse_error(msg: str) -> Tuple[list, str, None]: COALESCE(SUM(`usage` * rate), 0) AS cost FROM ( SELECT billing_project, `user`, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM aggregated_billing_project_user_resources_by_date_v2 - LEFT JOIN billing_projects ON billing_projects.name = aggregated_billing_project_user_resources_by_date_v2.billing_project + FROM aggregated_billing_project_user_resources_by_date_v3 + LEFT JOIN billing_projects ON billing_projects.name = aggregated_billing_project_user_resources_by_date_v3.billing_project WHERE {' AND '.join(where_conditions)} GROUP BY billing_project, `user`, resource_id ) AS t diff --git a/batch/batch/utils.py b/batch/batch/utils.py index aac9c71d6c1..e22ccca37c8 100644 --- a/batch/batch/utils.py +++ b/batch/batch/utils.py @@ -166,8 +166,8 @@ async def query_billing_projects_with_cost(db, user=None, billing_project=None): SELECT SUM(`usage` * rate) as cost FROM ( SELECT billing_project, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM aggregated_billing_project_user_resources_v2 - WHERE billing_projects.name = aggregated_billing_project_user_resources_v2.billing_project + FROM aggregated_billing_project_user_resources_v3 + WHERE billing_projects.name = aggregated_billing_project_user_resources_v3.billing_project GROUP BY billing_project, resource_id LOCK IN SHARE MODE ) AS usage_t From e922d6faed0e14eb1c3252d7039ebdeb4cf22afb Mon Sep 17 00:00:00 2001 From: Wenhan Lu <68076796+wlu04@users.noreply.github.com> Date: Thu, 10 Aug 2023 19:21:35 -0400 Subject: [PATCH 097/180] [query] changes in charr docstring (#13411) Hi all, I have made some quick edits in the docstring of the `hl.methods.qc.charr()` function. Please let me know if anything else is needed to clarify. Thanks! --- hail/python/hail/methods/qc.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hail/python/hail/methods/qc.py b/hail/python/hail/methods/qc.py index 35c2c66e7cf..b033eb89e8c 100644 --- a/hail/python/hail/methods/qc.py +++ b/hail/python/hail/methods/qc.py @@ -1761,7 +1761,11 @@ def compute_charr( It is possible to use gnomAD reference allele frequencies with the following: >>> gnomad_sites = hl.experimental.load_dataset('gnomad_genome_sites', version='3.1.2') # doctest: +SKIP - >>> charr_result = hl.compute_charr(mt, ref_af=(1 - gnomad_sites[mt.row_key].freq[1])) # doctest: +SKIP + >>> charr_result = hl.compute_charr(mt, ref_af=(1 - gnomad_sites[mt.row_key].freq[0])) # doctest: +SKIP + + If the dataset is loaded from a gvcf and has NON_REF alleles, drop the last allele with the following or load it with the hail vcf combiner: + + >>> mt = mt.key_rows_by(locus=mt.locus, alleles=mt.alleles[:-1]) Parameters ---------- From 5b6bc96a9092955d9fe37cdb6ec4f70815b34e32 Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 10 Aug 2023 20:47:29 -0400 Subject: [PATCH 098/180] [build.yaml] use an acocunt that actually has admin privs (#13415) --- build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.yaml b/build.yaml index f87458be6ce..5e794683447 100644 --- a/build.yaml +++ b/build.yaml @@ -3748,7 +3748,7 @@ steps: scopes: - deploy serviceAccount: - name: admin + name: ci-admin namespace: valueFrom: default_ns.name dependsOn: From 0f00dcd5f03f9355e805798de9fb9b6876d1292c Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 11 Aug 2023 02:26:13 -0400 Subject: [PATCH 099/180] [batch] Up network allocation timeout to a minute (#13412) --- batch/batch/worker/worker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index a7daa680b03..87c6d660999 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -1026,7 +1026,7 @@ async def _setup_overlay(self): async def _setup_network_namespace(self): assert network_allocator assert port_allocator - async with async_timeout.timeout(10): + async with async_timeout.timeout(60): if self.network == 'private': self.netns = await network_allocator.allocate_private() else: From 69168e5eedd62ee63a2b1ec4df47ef12e5bde540 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 11 Aug 2023 10:59:15 -0400 Subject: [PATCH 100/180] [gear] some trivial type annotations (#13419) --- gear/gear/database.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/gear/gear/database.py b/gear/gear/database.py index 487b31b275f..065d760af72 100644 --- a/gear/gear/database.py +++ b/gear/gear/database.py @@ -30,9 +30,13 @@ internal_error_retry_codes = (1205,) -def retry_transient_mysql_errors(f): +T = TypeVar("T") +P = ParamSpec('P') + + +def retry_transient_mysql_errors(f: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]: @functools.wraps(f) - async def wrapper(*args, **kwargs): + async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T: tries = 0 while True: try: @@ -61,10 +65,6 @@ async def wrapper(*args, **kwargs): return wrapper -T = TypeVar("T") -P = ParamSpec('P') - - def transaction(db: 'Database', read_only: bool = False): def transformer(fun: Callable[Concatenate['Transaction', P], Awaitable[T]]) -> Callable[P, Awaitable[T]]: @functools.wraps(fun) @@ -128,7 +128,9 @@ def get_database_ssl_context(sql_config: Optional[SQLConfig] = None) -> ssl.SSLC @retry_transient_mysql_errors -async def create_database_pool(config_file: Optional[str] = None, autocommit: bool = True, maxsize: int = 10): +async def create_database_pool( + config_file: Optional[str] = None, autocommit: bool = True, maxsize: int = 10 +) -> aiomysql.Pool: sql_config = get_sql_config(config_file) if get_deploy_config().location() != 'k8s' and sql_config.host.endswith('svc.cluster.local'): sql_config = await resolve_test_db_endpoint(sql_config) From d4a2f1d285d94885c660b3228f67d962fe04bbe5 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 11 Aug 2023 12:01:18 -0400 Subject: [PATCH 101/180] [ci] Use ci-agent not ci-admin for cron (#13420) `ci-agent` is the actual cluster admin service account that CI can use for batch jobs. `ci-admin` does not exist. --- build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.yaml b/build.yaml index 5e794683447..73abd220807 100644 --- a/build.yaml +++ b/build.yaml @@ -3748,7 +3748,7 @@ steps: scopes: - deploy serviceAccount: - name: ci-admin + name: ci-agent namespace: valueFrom: default_ns.name dependsOn: From 959a085e6c5dd8cdea8a4683cbe4997cbec47f6d Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 11 Aug 2023 14:03:33 -0400 Subject: [PATCH 102/180] [batch] monitor in prometheus/grafana the *schedulable* free cores (#13413) The "free" cores as written is less useful because it includes pending instances. --- batch/batch/driver/main.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 5644abbe24e..e9e7c9a288c 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -1271,6 +1271,7 @@ async def cancel_fast_failing_batches(app): ACTIVE_USER_INST_COLL_PAIRS: Set[Tuple[str, str]] = set() FREE_CORES = pc.Gauge('batch_free_cores', 'Batch total free cores', ['inst_coll']) +FREE_SCHEDULABLE_CORES = pc.Gauge('batch_free_schedulable_cores', 'Batch total free cores', ['inst_coll']) TOTAL_CORES = pc.Gauge('batch_total_cores', 'Batch total cores', ['inst_coll']) COST_PER_HOUR = pc.Gauge('batch_cost_per_hour', 'Batch cost ($/hr)', ['measure', 'inst_coll']) INSTANCES = pc.Gauge('batch_instances', 'Batch instances', ['inst_coll', 'state']) @@ -1339,6 +1340,7 @@ def monitor_instances(app) -> None: resource_rates = driver.billing_manager.resource_rates for inst_coll in inst_coll_manager.name_inst_coll.values(): + total_free_schedulable_cores = 0.0 total_free_cores = 0.0 total_cores = 0.0 total_cost_per_hour = 0.0 @@ -1346,6 +1348,8 @@ def monitor_instances(app) -> None: instances_by_state: Dict[str, int] = defaultdict(int) for instance in inst_coll.name_instance.values(): + if instance.state == 'active': + total_free_schedulable_cores += instance.free_cores_mcpu_nonnegative / 1000 if instance.state != 'deleted': total_free_cores += instance.free_cores_mcpu_nonnegative / 1000 total_cores += instance.cores_mcpu / 1000 @@ -1356,6 +1360,7 @@ def monitor_instances(app) -> None: instances_by_state[instance.state] += 1 FREE_CORES.labels(inst_coll=inst_coll.name).set(total_free_cores) + FREE_SCHEDULABLE_CORES.labels(inst_coll=inst_coll.name).set(total_free_schedulable_cores) TOTAL_CORES.labels(inst_coll=inst_coll.name).set(total_cores) COST_PER_HOUR.labels(inst_coll=inst_coll.name, measure='actual').set(total_cost_per_hour) COST_PER_HOUR.labels(inst_coll=inst_coll.name, measure='billed').set(total_revenue_per_hour) From 64cff7148faa4cbdc11531d51f05fe3feb9d309c Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 11 Aug 2023 15:14:31 -0400 Subject: [PATCH 103/180] [batch] ignore aiomysql warnings about batch.billing_projects.name (#13418) For example, see error messages when batch-driver shuts down: https://cloudlogging.app.goo.gl/kKgJdv34s3a6Vd8n6. --- batch/batch/driver/main.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index e9e7c9a288c..1ac60d8bb26 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -5,6 +5,7 @@ import os import re import signal +import warnings from collections import defaultdict, namedtuple from functools import wraps from typing import Any, Awaitable, Callable, Dict, Set, Tuple @@ -89,6 +90,12 @@ auth = AuthClient() +warnings.filterwarnings( + 'ignore', + ".*Warning: Field or reference 'batch.billing_projects.name' of SELECT #. was resolved in SELECT #.", + module='aiomysql.*', +) + def instance_name_from_request(request): instance_name = request.headers.get('X-Hail-Instance-Name') From 4623e55cd831b68f372c5445beb1bfe158bd9ea8 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 11 Aug 2023 16:21:31 -0400 Subject: [PATCH 104/180] [batch] show schedulable cores instead of schedulable + pending in pool, jpim, global (#13425) --- batch/batch/driver/instance_collection/base.py | 7 +++++++ batch/batch/driver/main.py | 2 +- batch/batch/driver/templates/index.html | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/batch/batch/driver/instance_collection/base.py b/batch/batch/driver/instance_collection/base.py index 435117c8072..f8d9c775c4e 100644 --- a/batch/batch/driver/instance_collection/base.py +++ b/batch/batch/driver/instance_collection/base.py @@ -96,6 +96,13 @@ def global_current_version_live_free_cores_mcpu(self): inst_coll.current_worker_version_stats.live_free_cores_mcpu for inst_coll in self.name_inst_coll.values() ) + @property + def global_current_version_live_schedulable_free_cores_mcpu(self): + return sum( + inst_coll.current_worker_version_stats.live_schedulable_free_cores_mcpu + for inst_coll in self.name_inst_coll.values() + ) + @property def global_n_instances_by_state(self) -> Counter[str]: return sum( diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 1ac60d8bb26..b1290ff69c9 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -472,7 +472,7 @@ async def get_index(request, userdata): 'instances': inst_coll_manager.name_instance.values(), 'ready_cores_mcpu': ready_cores_mcpu, 'total_provisioned_cores_mcpu': inst_coll_manager.global_total_provisioned_cores_mcpu, - 'live_free_cores_mcpu': inst_coll_manager.global_current_version_live_free_cores_mcpu, + 'live_schedulable_free_cores_mcpu': inst_coll_manager.global_current_version_live_schedulable_free_cores_mcpu, 'frozen': app['frozen'], 'feature_flags': app['feature_flags'], } diff --git a/batch/batch/driver/templates/index.html b/batch/batch/driver/templates/index.html index 11e582773c8..b6aa5f2b17c 100644 --- a/batch/batch/driver/templates/index.html +++ b/batch/batch/driver/templates/index.html @@ -102,7 +102,7 @@

Job Private Instance Manager

{{ jpim.all_versions_instances_by_state['inactive'] }} {{ jpim.all_versions_instances_by_state['deleted'] }} {{ jpim.all_versions_provisioned_cores_mcpu / 1000 }} - {{ jpim.current_worker_version_stats.live_free_cores_mcpu / 1000 }} / {{ jpim.all_versions_provisioned_cores_mcpu / 1000 }} + {{ jpim.current_worker_version_stats.live_schedulable_free_cores_mcpu / 1000 }} / {{ jpim.all_versions_provisioned_cores_mcpu / 1000 }} @@ -114,7 +114,7 @@

Instances

Inactive: {{ n_instances_by_state['inactive'] }}
Deleted: {{ n_instances_by_state['deleted'] }}
Total provisioned cores: {{ total_provisioned_cores_mcpu / 1000 }}
-
Total schedulable cores: {{ live_free_cores_mcpu / 1000 }} / {{ total_provisioned_cores_mcpu / 1000 }}
+
Total schedulable cores: {{ live_schedulable_free_cores_mcpu / 1000 }} / {{ total_provisioned_cores_mcpu / 1000 }}
From 32cb12921cca4832a1322015da1d37f121d9b506 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 11 Aug 2023 17:27:36 -0400 Subject: [PATCH 105/180] [build.yaml] finally fix up the namespace autoscaler (#13426) Alright! I stopped being lazy and actually tested all this. I copied the code from the step into a file and removed the left-hand indentation. I called that file `/tmp/foo.sh`. I ran this: ``` python3 ~/projects/hail/ci/jinja2_render.py '{"code":{"developers":[{"username":"cchurch"},{"username":"dking"},{"username":"jigold"},{"username":"dgoldste"}, {"username":"irademac"},{"username":"parsa"},{"username":"test-dev"},{"username":"cseed"},{"username":"cvittal"},{"username":"ehigham"},{"username":"gsmith"},{"username":"jwander"},{"username":"nwatts"},{"username":"pschultz"}]}}' \ /tmp/foo.sh \ /tmp/foo.sh.out sh /tmp/foo.sh.out ``` And it correctly skipped test-dev entirely, it printed "Skipping cchurch because they have no namespace." and it created the appropriate cronjobs for everyone else. I then re-ran it to verify it indicated no changes. I then listed all the cronjobs: ``` (base) dking@wm28c-761 hail % k get cronjob --all-namespaces NAMESPACE NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE cseed dev-namespace-scaledown-cseed 0 20 * * 1,2,3,4,5 False 0 13s cseed dev-namespace-scaleup-cseed 0 9 * * 1,2,3,4,5 False 0 90m cvittal dev-namespace-scaledown-cvittal 0 20 * * 1,2,3,4,5 False 0 12s cvittal dev-namespace-scaleup-cvittal 0 9 * * 1,2,3,4,5 False 0 90m dgoldste dev-namespace-scaledown-dgoldste 0 20 * * 1,2,3,4,5 False 0 4m2s dgoldste dev-namespace-scaleup-dgoldste 0 9 * * 1,2,3,4,5 False 0 90m dking dev-namespace-scaledown-dking 0 20 * * 1,2,3,4,5 False 0 9m22s dking dev-namespace-scaleup-dking 0 9 * * 1,2,3,4,5 False 0 90m ehigham dev-namespace-scaledown-ehigham 0 20 * * 1,2,3,4,5 False 0 11s ehigham dev-namespace-scaleup-ehigham 0 9 * * 1,2,3,4,5 False 0 90m gsmith dev-namespace-scaledown-gsmith 0 20 * * 1,2,3,4,5 False 0 10s gsmith dev-namespace-scaleup-gsmith 0 9 * * 1,2,3,4,5 False 0 90m irademac dev-namespace-scaledown-irademac 0 20 * * 1,2,3,4,5 False 0 4m2s irademac dev-namespace-scaleup-irademac 0 9 * * 1,2,3,4,5 False 0 90m jigold dev-namespace-scaledown-jigold 0 20 * * 1,2,3,4,5 False 0 4m3s jigold dev-namespace-scaleup-jigold 0 9 * * 1,2,3,4,5 False 0 90m jwander dev-namespace-scaledown-jwander 0 20 * * 1,2,3,4,5 False 0 10s jwander dev-namespace-scaleup-jwander 0 9 * * 1,2,3,4,5 False 0 90m nwatts dev-namespace-scaledown-nwatts 0 20 * * 1,2,3,4,5 False 0 9s nwatts dev-namespace-scaleup-nwatts 0 9 * * 1,2,3,4,5 False 0 90m parsa dev-namespace-scaledown-parsa 0 20 * * 1,2,3,4,5 False 0 4m1s parsa dev-namespace-scaleup-parsa 0 9 * * 1,2,3,4,5 False 0 90m pschultz dev-namespace-scaledown-pschultz 0 20 * * 1,2,3,4,5 False 0 8s pschultz dev-namespace-scaleup-pschultz 0 9 * * 1,2,3,4,5 False 0 90m ``` --- build.yaml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/build.yaml b/build.yaml index 73abd220807..a7022b4e22d 100644 --- a/build.yaml +++ b/build.yaml @@ -3690,16 +3690,19 @@ steps: valueFrom: ci_utils_image.image script: | set -ex - cat > dev-namespace-scalers.yaml <<'EOF' {% for user in code.get("developers", []) %} {% if user['username'] != 'test-dev' %} + + if kubectl get namespace {{ user["username"] }} 2>/dev/null + then + cat > the.yaml <<'EOF' apiVersion: batch/v1 kind: CronJob metadata: name: dev-namespace-scaledown-{{ user["username"] }} namespace: {{ user["username"] }} spec: - schedule: 0 20 * * 1,2,3,4,5" # Weekdays at 8p + schedule: "0 20 * * 1,2,3,4,5" # Weekdays at 8p concurrencyPolicy: Forbid successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 1 @@ -3709,7 +3712,7 @@ steps: spec: serviceAccountName: admin containers: - - name: dev-namespace-scaledown-dking + - name: dev-namespace-scaledown-{{ user["username"] }} image: bitnami/kubectl:latest command: - /bin/sh @@ -3741,10 +3744,18 @@ steps: - set -ex ; kubectl scale deployments --all -n {{ user["username"] }} --replicas=1 && kubectl scale statefulsets --all -n {{ user["username"] }} --replicas=1 restartPolicy: OnFailure --- + EOF + + kubectl apply -f the.yaml + echo "For {{ user["username"] }}, applied:" + echo "---" + cat the.yaml + else + echo "Skipping {{ user["username"] }} because they have no namespace." + fi + {% endif %} {% endfor %} - EOF - kubectl apply -f dev-namespace-scalers.yaml scopes: - deploy serviceAccount: From ca4ab159b43243963057d8e716353552008a60e9 Mon Sep 17 00:00:00 2001 From: jigold Date: Mon, 14 Aug 2023 16:31:20 -0400 Subject: [PATCH 106/180] [hailctl] Autocomplete for hailctl config {get,set,unset} (#13224) To get this to work, I had to run the following command: ``` hailctl --install-completion zsh ``` And then add this line to the end of the ~/.zshrc file: `autoload -Uz compinit && compinit` --- hail/python/hail/backend/backend.py | 4 +- hail/python/hail/backend/service_backend.py | 20 ++-- hail/python/hail/docs/install/macosx.rst | 11 +++ hail/python/hail/utils/java.py | 4 +- .../hailtop/aiocloud/aiogoogle/user_config.py | 6 +- hail/python/hailtop/batch/backend.py | 6 +- hail/python/hailtop/batch/batch.py | 4 +- hail/python/hailtop/config/__init__.py | 4 +- hail/python/hailtop/config/user_config.py | 32 +++++-- hail/python/hailtop/config/variables.py | 20 ++++ hail/python/hailtop/hailctl/config/cli.py | 73 +++++++++----- .../hailctl/config/config_variables.py | 94 +++++++++++++++++++ .../test/hailtop/hailctl/config/conftest.py | 32 +++++++ .../test/hailtop/hailctl/config/test_cli.py | 77 +++++++++++++-- hail/scripts/test_requester_pays_parsing.py | 9 +- 15 files changed, 324 insertions(+), 72 deletions(-) create mode 100644 hail/python/hailtop/config/variables.py create mode 100644 hail/python/hailtop/hailctl/config/config_variables.py diff --git a/hail/python/hail/backend/backend.py b/hail/python/hail/backend/backend.py index 2a93ad631b1..d193b2fb877 100644 --- a/hail/python/hail/backend/backend.py +++ b/hail/python/hail/backend/backend.py @@ -4,7 +4,7 @@ import pkg_resources import zipfile -from hailtop.config.user_config import configuration_of +from hailtop.config.user_config import unchecked_configuration_of from hailtop.fs.fs import FS from ..builtin_references import BUILTIN_REFERENCE_RESOURCE_PATHS @@ -197,7 +197,7 @@ def persist_expression(self, expr: Expression) -> Expression: def _initialize_flags(self, initial_flags: Dict[str, str]) -> None: self.set_flags(**{ - k: configuration_of('query', k, None, default, deprecated_envvar=deprecated_envvar) + k: unchecked_configuration_of('query', k, None, default, deprecated_envvar=deprecated_envvar) for k, (deprecated_envvar, default) in Backend._flags_env_vars_and_defaults.items() if k not in initial_flags }, **initial_flags) diff --git a/hail/python/hail/backend/service_backend.py b/hail/python/hail/backend/service_backend.py index 4c7d9aa8c8c..66a7823c039 100644 --- a/hail/python/hail/backend/service_backend.py +++ b/hail/python/hail/backend/service_backend.py @@ -19,7 +19,7 @@ from hail.ir.renderer import CSERenderer from hailtop import yamlx -from hailtop.config import (configuration_of, get_remote_tmpdir) +from hailtop.config import (ConfigVariable, configuration_of, get_remote_tmpdir) from hailtop.utils import async_to_blocking, secret_alnum_string, TransientError, Timings, am_i_interactive, retry_transient_errors from hailtop.utils.rich_progress_bar import BatchProgressBar from hailtop.batch_client import client as hb @@ -206,7 +206,7 @@ async def create(*, token: Optional[str] = None, regions: Optional[List[str]] = None, gcs_requester_pays_configuration: Optional[GCSRequesterPaysConfiguration] = None): - billing_project = configuration_of('batch', 'billing_project', billing_project, None) + billing_project = configuration_of(ConfigVariable.BATCH_BILLING_PROJECT, billing_project, None) if billing_project is None: raise ValueError( "No billing project. Call 'init_batch' with the billing " @@ -224,17 +224,17 @@ async def create(*, batch_attributes: Dict[str, str] = dict() remote_tmpdir = get_remote_tmpdir('ServiceBackend', remote_tmpdir=remote_tmpdir) - jar_url = configuration_of('query', 'jar_url', jar_url, None) + jar_url = configuration_of(ConfigVariable.QUERY_JAR_URL, jar_url, None) jar_spec = GitRevision(revision()) if jar_url is None else JarUrl(jar_url) - driver_cores = configuration_of('query', 'batch_driver_cores', driver_cores, None) - driver_memory = configuration_of('query', 'batch_driver_memory', driver_memory, None) - worker_cores = configuration_of('query', 'batch_worker_cores', worker_cores, None) - worker_memory = configuration_of('query', 'batch_worker_memory', worker_memory, None) - name_prefix = configuration_of('query', 'name_prefix', name_prefix, '') + driver_cores = configuration_of(ConfigVariable.QUERY_BATCH_DRIVER_CORES, driver_cores, None) + driver_memory = configuration_of(ConfigVariable.QUERY_BATCH_DRIVER_MEMORY, driver_memory, None) + worker_cores = configuration_of(ConfigVariable.QUERY_BATCH_WORKER_CORES, worker_cores, None) + worker_memory = configuration_of(ConfigVariable.QUERY_BATCH_WORKER_MEMORY, worker_memory, None) + name_prefix = configuration_of(ConfigVariable.QUERY_NAME_PREFIX, name_prefix, '') if regions is None: - regions_from_conf = configuration_of('batch', 'regions', regions, None) + regions_from_conf = configuration_of(ConfigVariable.BATCH_REGIONS, regions, None) if regions_from_conf is not None: assert isinstance(regions_from_conf, str) regions = regions_from_conf.split(',') @@ -245,7 +245,7 @@ async def create(*, assert len(regions) > 0, regions if disable_progress_bar is None: - disable_progress_bar_str = configuration_of('query', 'disable_progress_bar', None, None) + disable_progress_bar_str = configuration_of(ConfigVariable.QUERY_DISABLE_PROGRESS_BAR, None, None) if disable_progress_bar_str is None: disable_progress_bar = not am_i_interactive() else: diff --git a/hail/python/hail/docs/install/macosx.rst b/hail/python/hail/docs/install/macosx.rst index 5eb3f009e6b..8b9c8d6b9dc 100644 --- a/hail/python/hail/docs/install/macosx.rst +++ b/hail/python/hail/docs/install/macosx.rst @@ -14,3 +14,14 @@ Install Hail on Mac OS X - Install Python 3.9 or later. We recommend `Miniconda `__. - Open Terminal.app and execute ``pip install hail``. If this command fails with a message about "Rust", please try this instead: ``pip install hail --only-binary=:all:``. - `Run your first Hail query! `__ + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +hailctl Autocompletion (Optional) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Install autocompletion with ``hailctl --install-completion zsh`` +- Ensure this line is in your zsh config file (~/.zshrc) and then reload your terminal. + + .. code-block:: + + autoload -Uz compinit && compinit diff --git a/hail/python/hail/utils/java.py b/hail/python/hail/utils/java.py index a311884f99c..3f19d0d6e77 100644 --- a/hail/python/hail/utils/java.py +++ b/hail/python/hail/utils/java.py @@ -2,11 +2,11 @@ import sys import re -from hailtop.config import configuration_of +from hailtop.config import ConfigVariable, configuration_of def choose_backend(backend: Optional[str] = None) -> str: - return configuration_of('query', 'backend', backend, 'spark') + return configuration_of(ConfigVariable.QUERY_BACKEND, backend, 'spark') class HailUserError(Exception): diff --git a/hail/python/hailtop/aiocloud/aiogoogle/user_config.py b/hail/python/hailtop/aiocloud/aiogoogle/user_config.py index b6a713a91e5..53c4e832de3 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/user_config.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/user_config.py @@ -6,7 +6,7 @@ from dataclasses import dataclass -from hailtop.config.user_config import configuration_of +from hailtop.config.user_config import ConfigVariable, configuration_of GCSRequesterPaysConfiguration = Union[str, Tuple[str, List[str]]] @@ -19,8 +19,8 @@ def get_gcs_requester_pays_configuration( if gcs_requester_pays_configuration: return gcs_requester_pays_configuration - project = configuration_of('gcs_requester_pays', 'project', None, None) - buckets = configuration_of('gcs_requester_pays', 'buckets', None, None) + project = configuration_of(ConfigVariable.GCS_REQUESTER_PAYS_PROJECT, None, None) + buckets = configuration_of(ConfigVariable.GCS_REQUESTER_PAYS_BUCKETS, None, None) spark_conf = get_spark_conf_gcs_requester_pays_configuration() diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index 175aea1eb2c..ce066f00a9f 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -15,7 +15,7 @@ from rich.progress import track from hailtop import pip_version -from hailtop.config import configuration_of, get_deploy_config, get_remote_tmpdir +from hailtop.config import ConfigVariable, configuration_of, get_deploy_config, get_remote_tmpdir from hailtop.utils.rich_progress_bar import SimpleRichProgressBar from hailtop.utils import parse_docker_image_reference, async_to_blocking, bounded_gather, url_scheme from hailtop.batch.hail_genetics_images import HAIL_GENETICS_IMAGES, hailgenetics_python_dill_image_for_current_python_version @@ -474,7 +474,7 @@ def __init__(self, warnings.warn('Use of deprecated positional argument \'bucket\' in ServiceBackend(). Specify \'bucket\' as a keyword argument instead.') bucket = args[1] - billing_project = configuration_of('batch', 'billing_project', billing_project, None) + billing_project = configuration_of(ConfigVariable.BATCH_BILLING_PROJECT, billing_project, None) if billing_project is None: raise ValueError( 'the billing_project parameter of ServiceBackend must be set ' @@ -501,7 +501,7 @@ def __init__(self, self.__fs: RouterAsyncFS = RouterAsyncFS(gcs_kwargs=gcs_kwargs) if regions is None: - regions_from_conf = configuration_of('batch', 'regions', None, None) + regions_from_conf = configuration_of(ConfigVariable.BATCH_REGIONS, None, None) if regions_from_conf is not None: assert isinstance(regions_from_conf, str) regions = regions_from_conf.split(',') diff --git a/hail/python/hailtop/batch/batch.py b/hail/python/hailtop/batch/batch.py index e4d63eac114..8f5dba433b4 100644 --- a/hail/python/hailtop/batch/batch.py +++ b/hail/python/hailtop/batch/batch.py @@ -10,7 +10,7 @@ from hailtop.aiocloud.aioazure.fs import AzureAsyncFS from hailtop.aiotools.router_fs import RouterAsyncFS import hailtop.batch_client.client as _bc -from hailtop.config import configuration_of +from hailtop.config import ConfigVariable, configuration_of from . import backend as _backend, job, resource as _resource # pylint: disable=cyclic-import from .exceptions import BatchException @@ -167,7 +167,7 @@ def __init__(self, if backend: self._backend = backend else: - backend_config = configuration_of('batch', 'backend', None, 'local') + backend_config = configuration_of(ConfigVariable.BATCH_BACKEND, None, 'local') if backend_config == 'service': self._backend = _backend.ServiceBackend() else: diff --git a/hail/python/hailtop/config/__init__.py b/hail/python/hailtop/config/__init__.py index 4f5bc19a168..e8103674845 100644 --- a/hail/python/hailtop/config/__init__.py +++ b/hail/python/hailtop/config/__init__.py @@ -1,6 +1,7 @@ from .user_config import (get_user_config, get_user_config_path, get_remote_tmpdir, configuration_of) from .deploy_config import get_deploy_config, DeployConfig +from .variables import ConfigVariable __all__ = [ 'get_deploy_config', @@ -8,5 +9,6 @@ 'get_user_config_path', 'get_remote_tmpdir', 'DeployConfig', - 'configuration_of' + 'ConfigVariable', + 'configuration_of', ] diff --git a/hail/python/hailtop/config/user_config.py b/hail/python/hailtop/config/user_config.py index b54c075931b..fcd8c072faa 100644 --- a/hail/python/hailtop/config/user_config.py +++ b/hail/python/hailtop/config/user_config.py @@ -5,6 +5,8 @@ import warnings from pathlib import Path +from .variables import ConfigVariable + user_config = None @@ -36,15 +38,12 @@ def get_user_config() -> configparser.ConfigParser: T = TypeVar('T') -def configuration_of(section: str, - option: str, - explicit_argument: Optional[T], - fallback: T, - *, - deprecated_envvar: Optional[str] = None) -> Union[str, T]: - assert VALID_SECTION_AND_OPTION_RE.fullmatch(section), (section, option) - assert VALID_SECTION_AND_OPTION_RE.fullmatch(option), (section, option) - +def unchecked_configuration_of(section: str, + option: str, + explicit_argument: Optional[T], + fallback: T, + *, + deprecated_envvar: Optional[str] = None) -> Union[str, T]: if explicit_argument is not None: return explicit_argument @@ -69,6 +68,19 @@ def configuration_of(section: str, return fallback +def configuration_of(config_variable: ConfigVariable, + explicit_argument: Optional[T], + fallback: T, + *, + deprecated_envvar: Optional[str] = None) -> Union[str, T]: + if '/' in config_variable.value: + section, option = config_variable.value.split('/') + else: + section = 'global' + option = config_variable.value + return unchecked_configuration_of(section, option, explicit_argument, fallback, deprecated_envvar=deprecated_envvar) + + def get_remote_tmpdir(caller_name: str, *, bucket: Optional[str] = None, @@ -87,7 +99,7 @@ def get_remote_tmpdir(caller_name: str, raise ValueError(f'Cannot specify both \'remote_tmpdir\' and \'bucket\' in {caller_name}(...). Specify \'remote_tmpdir\' as a keyword argument instead.') if bucket is None and remote_tmpdir is None: - remote_tmpdir = configuration_of('batch', 'remote_tmpdir', None, None) + remote_tmpdir = configuration_of(ConfigVariable.BATCH_REMOTE_TMPDIR, None, None) if remote_tmpdir is None: if bucket is None: diff --git a/hail/python/hailtop/config/variables.py b/hail/python/hailtop/config/variables.py new file mode 100644 index 00000000000..3797679b13c --- /dev/null +++ b/hail/python/hailtop/config/variables.py @@ -0,0 +1,20 @@ +from enum import Enum + + +class ConfigVariable(str, Enum): + DOMAIN = 'domain' + GCS_REQUESTER_PAYS_PROJECT = 'gcs_requester_pays/project' + GCS_REQUESTER_PAYS_BUCKETS = 'gcs_requester_pays/buckets' + BATCH_BUCKET = 'batch/bucket' + BATCH_REMOTE_TMPDIR = 'batch/remote_tmpdir' + BATCH_REGIONS = 'batch/regions' + BATCH_BILLING_PROJECT = 'batch/billing_project' + BATCH_BACKEND = 'batch/backend' + QUERY_BACKEND = 'query/backend' + QUERY_JAR_URL = 'query/jar_url' + QUERY_BATCH_DRIVER_CORES = 'query/batch_driver_cores' + QUERY_BATCH_WORKER_CORES = 'query/batch_worker_cores' + QUERY_BATCH_DRIVER_MEMORY = 'query/batch_driver_memory' + QUERY_BATCH_WORKER_MEMORY = 'query/batch_worker_memory' + QUERY_NAME_PREFIX = 'query/name_prefix' + QUERY_DISABLE_PROGRESS_BAR = 'query/disable_progress_bar' diff --git a/hail/python/hailtop/hailctl/config/cli.py b/hail/python/hailtop/hailctl/config/cli.py index 273a078fcd7..b55039f4f31 100644 --- a/hail/python/hailtop/hailctl/config/cli.py +++ b/hail/python/hailtop/hailctl/config/cli.py @@ -1,13 +1,15 @@ import os import sys -import re -import warnings from typing import Optional, Tuple, Annotated as Ann +from rich import print import typer from typer import Argument as Arg +from hailtop.config.variables import ConfigVariable +from .config_variables import config_variables + app = typer.Typer( name='config', @@ -29,7 +31,7 @@ def get_section_key_path(parameter: str) -> Tuple[str, str, Tuple[str, ...]]: from the configuration parameter, for example: "batch/billing_project". Parameters may also have no slashes, indicating the parameter is a global -parameter, for example: "email". +parameter, for example: "domain". A parameter with more than one slash is invalid, for example: "batch/billing/project". @@ -41,35 +43,32 @@ def get_section_key_path(parameter: str) -> Tuple[str, str, Tuple[str, ...]]: sys.exit(1) +def complete_config_variable(incomplete: str): + for var, var_info in config_variables().items(): + if var.value.startswith(incomplete): + yield (var.value, var_info.help_msg) + + @app.command() -def set(parameter: str, value: str): +def set(parameter: Ann[ConfigVariable, Arg(help="Configuration variable to set", autocompletion=complete_config_variable)], value: str): '''Set a Hail configuration parameter.''' - from hailtop.aiotools.router_fs import RouterAsyncFS # pylint: disable=import-outside-toplevel from hailtop.config import get_user_config, get_user_config_path # pylint: disable=import-outside-toplevel - config = get_user_config() - config_file = get_user_config_path() - section, key, path = get_section_key_path(parameter) + if parameter not in config_variables(): + print(f"Error: unknown parameter {parameter!r}", file=sys.stderr) + sys.exit(1) - validations = { - ('batch', 'bucket'): ( - lambda x: re.fullmatch(r'[^:/\s]+', x) is not None, - 'should be valid Google Bucket identifier, with no gs:// prefix', - ), - ('batch', 'remote_tmpdir'): ( - RouterAsyncFS.valid_url, - 'should be valid cloud storage URI such as gs://my-bucket/batch-tmp/', - ), - ('email',): (lambda x: re.fullmatch(r'.+@.+', x) is not None, 'should be valid email address'), - } + section, key, _ = get_section_key_path(parameter.value) + + config_variable_info = config_variables()[parameter] + validation_func, error_msg = config_variable_info.validation - validation_func, msg = validations.get(path, (lambda _: True, '')) # type: ignore if not validation_func(value): - print(f"Error: bad value {value!r} for parameter {parameter!r} {msg}", file=sys.stderr) + print(f"Error: bad value {value!r} for parameter {parameter!r} {error_msg}", file=sys.stderr) sys.exit(1) - if path == ('batch', 'bucket'): - warnings.warn("'batch/bucket' has been deprecated. Use 'batch/remote_tmpdir' instead.") + config = get_user_config() + config_file = get_user_config_path() if section not in config: config[section] = {} @@ -84,8 +83,30 @@ def set(parameter: str, value: str): config.write(f) +def get_config_variable(incomplete: str): + from hailtop.config import get_user_config # pylint: disable=import-outside-toplevel + + config = get_user_config() + + elements = [] + for section_name, section in config.items(): + for item_name, value in section.items(): + if section_name == 'global': + path = item_name + else: + path = f'{section_name}/{item_name}' + elements.append((path, value)) + + config_items = {var.name: var_info.help_msg for var, var_info in config_variables().items()} + + for name, _ in elements: + if name.startswith(incomplete): + help_msg = config_items.get(name) + yield (name, help_msg) + + @app.command() -def unset(parameter: str): +def unset(parameter: Ann[str, Arg(help="Configuration variable to unset", autocompletion=get_config_variable)]): '''Unset a Hail configuration parameter (restore to default behavior).''' from hailtop.config import get_user_config, get_user_config_path # pylint: disable=import-outside-toplevel @@ -96,10 +117,12 @@ def unset(parameter: str): del config[section][key] with open(config_file, 'w', encoding='utf-8') as f: config.write(f) + else: + print(f"WARNING: Unknown parameter {parameter!r}", file=sys.stderr) @app.command() -def get(parameter: str): +def get(parameter: Ann[str, Arg(help="Configuration variable to get", autocompletion=get_config_variable)]): '''Get the value of a Hail configuration parameter.''' from hailtop.config import get_user_config # pylint: disable=import-outside-toplevel diff --git a/hail/python/hailtop/hailctl/config/config_variables.py b/hail/python/hailtop/hailctl/config/config_variables.py new file mode 100644 index 00000000000..8273f8b126a --- /dev/null +++ b/hail/python/hailtop/hailctl/config/config_variables.py @@ -0,0 +1,94 @@ +from collections import namedtuple +import re + +from hailtop.config import ConfigVariable + + +_config_variables = None + +ConfigVariableInfo = namedtuple('ConfigVariableInfo', ['help_msg', 'validation']) + + +def config_variables(): + from hailtop.batch_client.parse import CPU_REGEXPAT, MEMORY_REGEXPAT # pylint: disable=import-outside-toplevel + from hailtop.fs.router_fs import RouterAsyncFS # pylint: disable=import-outside-toplevel + + global _config_variables + + if _config_variables is None: + _config_variables = { + ConfigVariable.DOMAIN: ConfigVariableInfo( + help_msg='Domain of the Batch service', + validation=(lambda x: re.fullmatch(r'.+\..+', x) is not None, 'should be valid domain'), + ), + ConfigVariable.GCS_REQUESTER_PAYS_PROJECT: ConfigVariableInfo( + help_msg='Project when using requester pays buckets in GCS', + validation=(lambda x: re.fullmatch(r'[^:/\s]+', x) is not None, 'should be valid GCS project name'), + ), + ConfigVariable.GCS_REQUESTER_PAYS_BUCKETS: ConfigVariableInfo( + help_msg='Allowed buckets when using requester pays in GCS', + validation=( + lambda x: re.fullmatch(r'[^:/\s]+(,[^:/\s]+)*', x) is not None, + 'should be comma separated list of bucket names'), + ), + ConfigVariable.BATCH_BUCKET: ConfigVariableInfo( + help_msg='Deprecated - Name of GCS bucket to use as a temporary scratch directory', + validation=(lambda x: re.fullmatch(r'[^:/\s]+', x) is not None, + 'should be valid Google Bucket identifier, with no gs:// prefix'), + ), + ConfigVariable.BATCH_REMOTE_TMPDIR: ConfigVariableInfo( + help_msg='Cloud storage URI to use as a temporary scratch directory', + validation=(RouterAsyncFS.valid_url, 'should be valid cloud storage URI such as gs://my-bucket/batch-tmp/'), + ), + ConfigVariable.BATCH_REGIONS: ConfigVariableInfo( + help_msg='Comma-separated list of regions to run jobs in', + validation=( + lambda x: re.fullmatch(r'[^\s]+(,[^\s]+)*', x) is not None, 'should be comma separated list of regions'), + ), + ConfigVariable.BATCH_BILLING_PROJECT: ConfigVariableInfo( + help_msg='Batch billing project', + validation=(lambda x: re.fullmatch(r'[^:/\s]+', x) is not None, 'should be valid Batch billing project name'), + ), + ConfigVariable.BATCH_BACKEND: ConfigVariableInfo( + help_msg='Backend to use. One of local or service.', + validation=(lambda x: x in ('local', 'service'), 'should be one of "local" or "service"'), + ), + ConfigVariable.QUERY_BACKEND: ConfigVariableInfo( + help_msg='Backend to use for Hail Query. One of spark, local, batch.', + validation=(lambda x: x in ('local', 'spark', 'batch'), 'should be one of "local", "spark", or "batch"'), + ), + ConfigVariable.QUERY_JAR_URL: ConfigVariableInfo( + help_msg='Cloud storage URI to a Query JAR', + validation=(RouterAsyncFS.valid_url, 'should be valid cloud storage URI such as gs://my-bucket/jars/sha.jar') + ), + ConfigVariable.QUERY_BATCH_DRIVER_CORES: ConfigVariableInfo( + help_msg='Cores specification for the query driver', + validation=(lambda x: re.fullmatch(CPU_REGEXPAT, x) is not None, + 'should be an integer which is a power of two from 1 to 16 inclusive'), + ), + ConfigVariable.QUERY_BATCH_WORKER_CORES: ConfigVariableInfo( + help_msg='Cores specification for the query worker', + validation=(lambda x: re.fullmatch(CPU_REGEXPAT, x) is not None, + 'should be an integer which is a power of two from 1 to 16 inclusive'), + ), + ConfigVariable.QUERY_BATCH_DRIVER_MEMORY: ConfigVariableInfo( + help_msg='Memory specification for the query driver', + validation=(lambda x: re.fullmatch(MEMORY_REGEXPAT, x) is not None or x in ('standard', 'lowmem', 'highmem'), + 'should be a valid string specifying memory "[+]?((?:[0-9]*[.])?[0-9]+)([KMGTP][i]?)?B?" or one of standard, lowmem, highmem'), + ), + ConfigVariable.QUERY_BATCH_WORKER_MEMORY: ConfigVariableInfo( + help_msg='Memory specification for the query worker', + validation=(lambda x: re.fullmatch(MEMORY_REGEXPAT, x) is not None or x in ('standard', 'lowmem', 'highmem'), + 'should be a valid string specifying memory "[+]?((?:[0-9]*[.])?[0-9]+)([KMGTP][i]?)?B?" or one of standard, lowmem, highmem'), + ), + ConfigVariable.QUERY_NAME_PREFIX: ConfigVariableInfo( + help_msg='Name used when displaying query progress in a progress bar', + validation=(lambda x: re.fullmatch(r'[^\s]+', x) is not None, 'should be single word without spaces'), + ), + ConfigVariable.QUERY_DISABLE_PROGRESS_BAR: ConfigVariableInfo( + help_msg='Disable the progress bar with a value of 1. Enable the progress bar with a value of 0', + validation=(lambda x: x in ('0', '1'), 'should be a value of 0 or 1'), + ), + } + + return _config_variables diff --git a/hail/python/test/hailtop/hailctl/config/conftest.py b/hail/python/test/hailtop/hailctl/config/conftest.py index 95ca40e0f4d..8818cfa3e0c 100644 --- a/hail/python/test/hailtop/hailctl/config/conftest.py +++ b/hail/python/test/hailtop/hailctl/config/conftest.py @@ -1,3 +1,4 @@ +import os import pytest import tempfile @@ -13,3 +14,34 @@ def config_dir(): @pytest.fixture def runner(config_dir): yield CliRunner(mix_stderr=False, env={'XDG_CONFIG_HOME': config_dir}) + + +@pytest.fixture +def bc_runner(config_dir): + from hailtop.config import get_user_config, get_user_config_path # pylint: disable=import-outside-toplevel + + # necessary for backwards compatibility test + os.environ['XDG_CONFIG_HOME'] = config_dir + + config = get_user_config() + config_file = get_user_config_path() + + items = [ + ('global', 'email', 'johndoe@gmail.com'), + ('batch', 'foo', '5') + ] + + for section, key, value in items: + if section not in config: + config[section] = {} + config[section][key] = value + + try: + f = open(config_file, 'w', encoding='utf-8') + except FileNotFoundError: + os.makedirs(config_file.parent, exist_ok=True) + f = open(config_file, 'w', encoding='utf-8') + with f: + config.write(f) + + yield CliRunner(mix_stderr=False, env={'XDG_CONFIG_HOME': config_dir}) diff --git a/hail/python/test/hailtop/hailctl/config/test_cli.py b/hail/python/test/hailtop/hailctl/config/test_cli.py index d5f07937d61..3a595aeb81c 100644 --- a/hail/python/test/hailtop/hailctl/config/test_cli.py +++ b/hail/python/test/hailtop/hailctl/config/test_cli.py @@ -2,7 +2,8 @@ from typer.testing import CliRunner -from hailtop.hailctl.config import cli +from hailtop.config.variables import ConfigVariable +from hailtop.hailctl.config import cli, config_variables def test_config_location(runner: CliRunner, config_dir: str): @@ -20,42 +21,98 @@ def test_config_list_empty_config(runner: CliRunner): @pytest.mark.parametrize( 'name,value', [ - ('batch/backend', 'batch'), + ('domain', 'azure.hail.is'), + ('gcs_requester_pays/project', 'hail-vdc'), + ('gcs_requester_pays/buckets', 'hail,foo'), + ('batch/backend', 'service'), ('batch/billing_project', 'test'), + ('batch/regions', 'us-central1,us-east1'), ('batch/remote_tmpdir', 'gs://foo/bar'), ('query/backend', 'spark'), - - # hailctl currently accepts arbitrary settings - ('foo/bar', 'baz'), + ('query/jar_url', 'gs://foo/bar.jar'), + ('query/batch_driver_cores', '1'), + ('query/batch_worker_cores', '1'), + ('query/batch_driver_memory', '1Gi'), + ('query/batch_worker_memory', 'standard'), + ('query/name_prefix', 'foo'), + ('query/disable_progress_bar', '1'), ], ) -def test_config_set(name: str, value: str, runner: CliRunner): +def test_config_set_get_list_unset(name: str, value: str, runner: CliRunner): runner.invoke(cli.app, ['set', name, value], catch_exceptions=False) res = runner.invoke(cli.app, 'list', catch_exceptions=False) assert res.exit_code == 0 + if '/' not in name: + name = f'global/{name}' assert res.stdout.strip() == f'{name}={value}' res = runner.invoke(cli.app, ['get', name], catch_exceptions=False) assert res.exit_code == 0 assert res.stdout.strip() == value + res = runner.invoke(cli.app, ['unset', name], catch_exceptions=False) + assert res.exit_code == 0 -def test_config_get_bad_names(runner: CliRunner): - res = runner.invoke(cli.app, ['get', 'foo'], catch_exceptions=False) + res = runner.invoke(cli.app, 'list', catch_exceptions=False) assert res.exit_code == 0 assert res.stdout.strip() == '' - res = runner.invoke(cli.app, ['get', '/a/b/c'], catch_exceptions=False) - assert res.exit_code == 1 + +# backwards compatibility +def test_config_get_unknown_names(bc_runner: CliRunner): + res = bc_runner.invoke(cli.app, ['get', 'email'], catch_exceptions=False) + assert res.exit_code == 0 + assert res.stdout.strip() == 'johndoe@gmail.com' + + res = bc_runner.invoke(cli.app, ['get', 'batch/foo'], catch_exceptions=False) + assert res.exit_code == 0 + assert res.stdout.strip() == '5' @pytest.mark.parametrize( 'name,value', [ + ('foo/bar', 'baz'), + ], +) +def test_config_set_unknown_name(name: str, value: str, runner: CliRunner): + res = runner.invoke(cli.app, ['set', name, value], catch_exceptions=False) + assert res.exit_code == 2 + + +def test_config_unset_unknown_name(runner: CliRunner): + # backwards compatibility + res = runner.invoke(cli.app, ['unset', 'foo'], catch_exceptions=False) + assert res.exit_code == 0 + + res = runner.invoke(cli.app, ['unset', 'foo/bar'], catch_exceptions=False) + assert res.exit_code == 0 + + +@pytest.mark.parametrize( + 'name,value', + [ + ('domain', 'foo'), + ('gcs_requester_pays/project', 'gs://foo/bar'), + ('gcs_requester_pays/buckets', 'gs://foo/bar'), + ('batch/backend', 'foo'), + ('batch/billing_project', 'gs://foo/bar'), ('batch/remote_tmpdir', 'asdf://foo/bar'), + ('query/backend', 'random_backend'), + ('query/jar_url', 'bar://foo/bar.jar'), + ('query/batch_driver_cores', 'a'), + ('query/batch_worker_cores', 'b'), + ('query/batch_driver_memory', '1bar'), + ('query/batch_worker_memory', 'random'), + ('query/disable_progress_bar', '2'), ], ) def test_config_set_bad_value(name: str, value: str, runner: CliRunner): res = runner.invoke(cli.app, ['set', name, value], catch_exceptions=False) assert res.exit_code == 1 + + +def test_all_config_variables_in_map(): + for variable in ConfigVariable: + assert variable in config_variables.config_variables() diff --git a/hail/scripts/test_requester_pays_parsing.py b/hail/scripts/test_requester_pays_parsing.py index 4bdc9c2a6a2..d4d11e7699e 100644 --- a/hail/scripts/test_requester_pays_parsing.py +++ b/hail/scripts/test_requester_pays_parsing.py @@ -4,8 +4,8 @@ from hailtop.aiocloud.aiogoogle import get_gcs_requester_pays_configuration from hailtop.aiocloud.aiogoogle.user_config import spark_conf_path, get_spark_conf_gcs_requester_pays_configuration -from hailtop.utils.process import check_exec_output -from hailtop.config.user_config import configuration_of +from hailtop.utils.process import CalledProcessError, check_exec_output +from hailtop.config.user_config import ConfigVariable, configuration_of if 'YOU_MAY_OVERWRITE_MY_SPARK_DEFAULTS_CONF_AND_HAILCTL_SETTINGS' not in os.environ: @@ -15,6 +15,7 @@ SPARK_CONF_PATH = spark_conf_path() + async def unset_hailctl(): await check_exec_output( 'hailctl', @@ -141,8 +142,8 @@ async def test_hailctl_takes_precedence_1(): actual = get_gcs_requester_pays_configuration() assert actual == 'hailctl_project', str(( - configuration_of('gcs_requester_pays', 'project', None, None), - configuration_of('gcs_requester_pays', 'buckets', None, None), + configuration_of(ConfigVariable.GCS_REQUESTER_PAYS_PROJECT, None, None), + configuration_of(ConfigVariable.GCS_REQUESTER_PAYS_BUCKETS, None, None), get_spark_conf_gcs_requester_pays_configuration(), open('/Users/dking/.config/hail/config.ini', 'r').readlines() )) From f889f763c45d52f8960e948f11829fbb961e524c Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 15 Aug 2023 13:05:34 -0400 Subject: [PATCH 107/180] [query] Reset custom references after a test finishes (#13423) --- hail/python/test/hail/conftest.py | 4 ++++ hail/python/test/hail/helpers.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hail/python/test/hail/conftest.py b/hail/python/test/hail/conftest.py index c7ee113ce48..fe7cf873ed9 100644 --- a/hail/python/test/hail/conftest.py +++ b/hail/python/test/hail/conftest.py @@ -71,6 +71,10 @@ def set_query_name(init_hail, request): backend.batch_attributes = dict(name=request.node.name) yield backend.batch_attributes = dict() + references = list(backend._references.keys()) + for rg in references: + backend.remove_reference(rg) + backend.initialize_references() if backend._batch: report: Dict[str, CollectReport] = request.node.stash[test_results_key] if any(r.failed for r in report.values()): diff --git a/hail/python/test/hail/helpers.py b/hail/python/test/hail/helpers.py index 8b4708bccc0..ab76c88601e 100644 --- a/hail/python/test/hail/helpers.py +++ b/hail/python/test/hail/helpers.py @@ -4,7 +4,7 @@ import pytest from decorator import decorator -from hail.utils.java import Env, choose_backend +from hail.utils.java import choose_backend import hail as hl From a238167d50b235b41dbbb3d7a8a35f9de27b6c0f Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 15 Aug 2023 16:57:22 -0400 Subject: [PATCH 108/180] [aiogoogle] Fix bucket name parsing (#13435) This code was broken if the URL only had a bucket name like `gs://foo`. It truncated the last character of the bucket because the `find` operation returned -1 for not being able to find another `/` in the URL after `gs://`. --- .../hailtop/aiocloud/aiogoogle/client/storage_client.py | 8 ++++++-- hail/python/test/hailtop/test_aiogoogle.py | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py b/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py index ee217f11911..c9cc519fa87 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py @@ -615,8 +615,12 @@ def get_bucket_and_name(url: str) -> Tuple[str, str]: raise ValueError(f'Google Cloud Storage URI must be of the form: gs://bucket/path, found: {url}') end_of_bucket = rest.find('/', 2) - bucket = rest[2:end_of_bucket] - name = rest[(end_of_bucket + 1):] + if end_of_bucket != -1: + bucket = rest[2:end_of_bucket] + name = rest[(end_of_bucket + 1):] + else: + bucket = rest[2:] + name = '' return (bucket, name) diff --git a/hail/python/test/hailtop/test_aiogoogle.py b/hail/python/test/hailtop/test_aiogoogle.py index 857ebfef620..066deeb9b9b 100644 --- a/hail/python/test/hailtop/test_aiogoogle.py +++ b/hail/python/test/hailtop/test_aiogoogle.py @@ -41,6 +41,14 @@ def bucket_and_temporary_file(): return bucket, prefix + '/' + secrets.token_hex(16) +def test_bucket_path_parsing(): + bucket, prefix = GoogleStorageAsyncFS.get_bucket_and_name('gs://foo') + assert bucket == 'foo' and prefix == '' + + bucket, prefix = GoogleStorageAsyncFS.get_bucket_and_name('gs://foo/bar/baz') + assert bucket == 'foo' and prefix == 'bar/baz' + + @pytest.mark.asyncio async def test_get_object_metadata(bucket_and_temporary_file): bucket, file = bucket_and_temporary_file From 59a9d0dae10be949872e0343548572fa4e05321c Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 15 Aug 2023 19:40:50 -0400 Subject: [PATCH 109/180] [batch] Raise instead of returning aiohttp objects that subclass Exception (#13379) Returning HTTP status objects that subclass `Exception` [is deprecated](https://docs.aiohttp.org/en/stable/web_quickstart.html#exceptions) and will at some point block an upgrade to a higher version of aiohttp. --- auth/auth/auth.py | 48 ++++++++++----------- batch/batch/driver/main.py | 32 +++++++------- batch/batch/front_end/front_end.py | 38 ++++++++-------- ci/ci/ci.py | 30 ++++++------- gear/gear/auth.py | 8 ++-- hail/python/hailtop/config/deploy_config.py | 6 +-- notebook/notebook/notebook.py | 26 +++++------ 7 files changed, 94 insertions(+), 94 deletions(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index 036bdef9de3..76ae430cc6f 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -4,7 +4,7 @@ import os import re from functools import wraps -from typing import List, Optional +from typing import List, NoReturn, Optional import aiohttp_session import kubernetes_asyncio.client @@ -241,7 +241,7 @@ async def creating_account(request: web.Request, userdata: Optional[UserData]) - if user is None: set_message(session, f'Account does not exist for login id {login_id}.', 'error') - return web.HTTPFound(deploy_config.external_url('auth', '')) + raise web.HTTPFound(deploy_config.external_url('auth', '')) page_context = {'username': user['username'], 'state': user['state'], 'login_id': user['login_id']} @@ -252,7 +252,7 @@ async def creating_account(request: web.Request, userdata: Optional[UserData]) - session_id = await create_session(db, user['id']) session['session_id'] = session_id set_message(session, f'Account has been created for {user["username"]}.', 'info') - return web.HTTPFound(next_page) + raise web.HTTPFound(next_page) assert user['state'] == 'creating' session['pending'] = True @@ -277,7 +277,7 @@ async def _wait_websocket(request, login_id): user = await user_from_login_id(db, login_id) if not user: - return web.HTTPNotFound() + raise web.HTTPNotFound() ws = web.WebSocketResponse() await ws.prepare(request) @@ -310,7 +310,7 @@ async def _wait_websocket(request, login_id): @routes.get('/signup') -async def signup(request): +async def signup(request) -> NoReturn: next_page = request.query.get('next', deploy_config.external_url('auth', '/user')) flow_data = request.app['flow_client'].initiate_flow(deploy_config.external_url('auth', '/oauth2callback')) @@ -321,11 +321,11 @@ async def signup(request): session['caller'] = 'signup' session['flow'] = flow_data - return web.HTTPFound(flow_data['authorization_url']) + raise web.HTTPFound(flow_data['authorization_url']) @routes.get('/login') -async def login(request): +async def login(request) -> NoReturn: next_page = request.query.get('next', deploy_config.external_url('auth', '/user')) flow_data = request.app['flow_client'].initiate_flow(deploy_config.external_url('auth', '/oauth2callback')) @@ -336,11 +336,11 @@ async def login(request): session['caller'] = 'login' session['flow'] = flow_data - return web.HTTPFound(flow_data['authorization_url']) + raise web.HTTPFound(flow_data['authorization_url']) @routes.get('/oauth2callback') -async def callback(request): +async def callback(request) -> web.Response: session = await aiohttp_session.get_session(request) if 'flow' not in session: raise web.HTTPUnauthorized() @@ -370,7 +370,7 @@ async def callback(request): if user is None: if caller == 'login': set_message(session, f'Account does not exist for login id {login_id}', 'error') - return web.HTTPFound(deploy_config.external_url('auth', '')) + raise web.HTTPFound(deploy_config.external_url('auth', '')) assert caller == 'signup' @@ -384,12 +384,12 @@ async def callback(request): await insert_new_user(db, username, login_id, is_developer=False, is_service_account=False) except AuthUserError as e: set_message(session, e.message, 'error') - return web.HTTPFound(deploy_config.external_url('auth', '')) + raise web.HTTPFound(deploy_config.external_url('auth', '')) session['pending'] = True session['login_id'] = login_id - return web.HTTPFound(creating_url) + raise web.HTTPFound(creating_url) if user['state'] in ('deleting', 'deleted'): page_context = {'username': user['username'], 'state': user['state'], 'login_id': user['login_id']} @@ -402,14 +402,14 @@ async def callback(request): set_message(session, f'Account for login id {login_id} is still being created.', 'error') session['pending'] = True session['login_id'] = user['login_id'] - return web.HTTPFound(creating_url) + raise web.HTTPFound(creating_url) assert user['state'] == 'active' if caller == 'signup': set_message(session, f'Account has already been created for {user["username"]}.', 'info') session_id = await create_session(db, user['id']) session['session_id'] = session_id - return web.HTTPFound(next_page) + raise web.HTTPFound(next_page) @routes.post('/api/v1alpha/users/{user}/create') @@ -483,9 +483,9 @@ async def get_copy_paste_token_api(request: web.Request, userdata: UserData) -> @routes.post('/logout') @check_csrf_token @maybe_authenticated_user -async def logout(request: web.Request, userdata: Optional[UserData]) -> web.HTTPFound: +async def logout(request: web.Request, userdata: Optional[UserData]) -> NoReturn: if not userdata: - return web.HTTPFound(deploy_config.external_url('auth', '')) + raise web.HTTPFound(deploy_config.external_url('auth', '')) db = request.app['db'] session_id = userdata['session_id'] @@ -494,7 +494,7 @@ async def logout(request: web.Request, userdata: Optional[UserData]) -> web.HTTP session = await aiohttp_session.get_session(request) cleanup_session(session) - return web.HTTPFound(deploy_config.external_url('auth', '')) + raise web.HTTPFound(deploy_config.external_url('auth', '')) @routes.get('/api/v1alpha/login') @@ -522,7 +522,7 @@ async def get_roles(request: web.Request, userdata: UserData) -> web.Response: @routes.post('/roles') @check_csrf_token @authenticated_devs_only -async def post_create_role(request: web.Request, _) -> web.HTTPFound: +async def post_create_role(request: web.Request, _) -> NoReturn: session = await aiohttp_session.get_session(request) db = request.app['db'] post = await request.post() @@ -538,7 +538,7 @@ async def post_create_role(request: web.Request, _) -> web.HTTPFound: set_message(session, f'Created role {role_id} {name}.', 'info') - return web.HTTPFound(deploy_config.external_url('auth', '/roles')) + raise web.HTTPFound(deploy_config.external_url('auth', '/roles')) @routes.get('/users') @@ -553,7 +553,7 @@ async def get_users(request: web.Request, userdata: UserData) -> web.Response: @routes.post('/users') @check_csrf_token @authenticated_devs_only -async def post_create_user(request: web.Request, _) -> web.HTTPFound: +async def post_create_user(request: web.Request, _) -> NoReturn: session = await aiohttp_session.get_session(request) db = request.app['db'] post = await request.post() @@ -566,14 +566,14 @@ async def post_create_user(request: web.Request, _) -> web.HTTPFound: created_user = await insert_new_user(db, username, login_id, is_developer, is_service_account) except AuthUserError as e: set_message(session, e.message, 'error') - return web.HTTPFound(deploy_config.external_url('auth', '/users')) + raise web.HTTPFound(deploy_config.external_url('auth', '/users')) if created_user: set_message(session, f'Created user {username} {login_id}.', 'info') else: set_message(session, f'User {username} {login_id} already exists.', 'info') - return web.HTTPFound(deploy_config.external_url('auth', '/users')) + raise web.HTTPFound(deploy_config.external_url('auth', '/users')) @routes.get('/api/v1alpha/users') @@ -633,7 +633,7 @@ async def _delete_user(db: Database, username: str, id: Optional[str]): @routes.post('/users/delete') @check_csrf_token @authenticated_devs_only -async def delete_user(request: web.Request, _) -> web.HTTPFound: +async def delete_user(request: web.Request, _) -> NoReturn: session = await aiohttp_session.get_session(request) db = request.app['db'] post = await request.post() @@ -646,7 +646,7 @@ async def delete_user(request: web.Request, _) -> web.HTTPFound: except UnknownUser: set_message(session, f'Delete failed, no such user {id} {username}.', 'error') - return web.HTTPFound(deploy_config.external_url('auth', '/users')) + raise web.HTTPFound(deploy_config.external_url('auth', '/users')) @routes.delete('/api/v1alpha/users/{user}') diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index b1290ff69c9..4c457fe6ba4 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -8,7 +8,7 @@ import warnings from collections import defaultdict, namedtuple from functools import wraps -from typing import Any, Awaitable, Callable, Dict, Set, Tuple +from typing import Any, Awaitable, Callable, Dict, NoReturn, Set, Tuple import aiohttp_session import dictdiffer @@ -308,7 +308,7 @@ async def deactivate_instance(_, instance: Instance) -> web.Response: @routes.post('/instances/{instance_name}/kill') @check_csrf_token @auth.web_authenticated_developers_only() -async def kill_instance(request: web.Request, _) -> web.HTTPFound: +async def kill_instance(request: web.Request, _) -> NoReturn: instance_name = request.match_info['instance_name'] inst_coll_manager: InstanceCollectionManager = request.app['driver'].inst_coll_manager @@ -326,7 +326,7 @@ async def kill_instance(request: web.Request, _) -> web.HTTPFound: pool_name = instance.inst_coll.name pool_url_path = f'/inst_coll/pool/{pool_name}' - return web.HTTPFound(deploy_config.external_url('batch-driver', pool_url_path)) + raise web.HTTPFound(deploy_config.external_url('batch-driver', pool_url_path)) async def job_complete_1(request, instance): @@ -571,7 +571,7 @@ def validate_int(session, name, value, predicate, description): @routes.post('/configure-feature-flags') @check_csrf_token @auth.web_authenticated_developers_only() -async def configure_feature_flags(request: web.Request, _) -> web.HTTPFound: +async def configure_feature_flags(request: web.Request, _) -> NoReturn: app = request.app db: Database = app['db'] post = await request.post() @@ -589,13 +589,13 @@ async def configure_feature_flags(request: web.Request, _) -> web.HTTPFound: row = await db.select_and_fetchone('SELECT * FROM feature_flags') app['feature_flags'] = row - return web.HTTPFound(deploy_config.external_url('batch-driver', '/')) + raise web.HTTPFound(deploy_config.external_url('batch-driver', '/')) @routes.post('/config-update/pool/{pool}') @check_csrf_token @auth.web_authenticated_developers_only() -async def pool_config_update(request: web.Request, _) -> web.HTTPFound: +async def pool_config_update(request: web.Request, _) -> NoReturn: app = request.app db: Database = app['db'] inst_coll_manager: InstanceCollectionManager = app['driver'].inst_coll_manager @@ -795,13 +795,13 @@ async def pool_config_update(request: web.Request, _) -> web.HTTPFound: log.exception(f'error while updating pool configuration for {pool}') raise - return web.HTTPFound(deploy_config.external_url('batch-driver', pool_url_path)) + raise web.HTTPFound(deploy_config.external_url('batch-driver', pool_url_path)) @routes.post('/config-update/jpim') @check_csrf_token @auth.web_authenticated_developers_only() -async def job_private_config_update(request: web.Request, _) -> web.HTTPFound: +async def job_private_config_update(request: web.Request, _) -> NoReturn: app = request.app jpim: JobPrivateInstanceManager = app['driver'].job_private_inst_manager @@ -874,7 +874,7 @@ async def job_private_config_update(request: web.Request, _) -> web.HTTPFound: log.exception(f'error while updating pool configuration for {jpim}') raise - return web.HTTPFound(deploy_config.external_url('batch-driver', url_path)) + raise web.HTTPFound(deploy_config.external_url('batch-driver', url_path)) @routes.get('/inst_coll/pool/{pool}') @@ -890,7 +890,7 @@ async def get_pool(request, userdata): if not isinstance(pool, Pool): set_message(session, f'Unknown pool {pool_name}.', 'error') - return web.HTTPFound(deploy_config.external_url('batch-driver', '/')) + raise web.HTTPFound(deploy_config.external_url('batch-driver', '/')) user_resources = await pool.scheduler.compute_fair_share() user_resources = sorted( @@ -946,14 +946,14 @@ async def get_job_private_inst_manager(request, userdata): @routes.post('/freeze') @check_csrf_token @auth.web_authenticated_developers_only() -async def freeze_batch(request: web.Request, _) -> web.HTTPFound: +async def freeze_batch(request: web.Request, _) -> NoReturn: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) if app['frozen']: set_message(session, 'Batch is already frozen.', 'info') - return web.HTTPFound(deploy_config.external_url('batch-driver', '/')) + raise web.HTTPFound(deploy_config.external_url('batch-driver', '/')) await db.execute_update( ''' @@ -965,20 +965,20 @@ async def freeze_batch(request: web.Request, _) -> web.HTTPFound: set_message(session, 'Froze all instance collections and batch submissions.', 'info') - return web.HTTPFound(deploy_config.external_url('batch-driver', '/')) + raise web.HTTPFound(deploy_config.external_url('batch-driver', '/')) @routes.post('/unfreeze') @check_csrf_token @auth.web_authenticated_developers_only() -async def unfreeze_batch(request: web.Request, _) -> web.HTTPFound: +async def unfreeze_batch(request: web.Request, _) -> NoReturn: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) if not app['frozen']: set_message(session, 'Batch is already unfrozen.', 'info') - return web.HTTPFound(deploy_config.external_url('batch-driver', '/')) + raise web.HTTPFound(deploy_config.external_url('batch-driver', '/')) await db.execute_update( ''' @@ -990,7 +990,7 @@ async def unfreeze_batch(request: web.Request, _) -> web.HTTPFound: set_message(session, 'Unfroze all instance collections and batch submissions.', 'info') - return web.HTTPFound(deploy_config.external_url('batch-driver', '/')) + raise web.HTTPFound(deploy_config.external_url('batch-driver', '/')) @routes.get('/user_resources') diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index c62ff417579..4badd5dea48 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -11,7 +11,7 @@ import traceback from functools import wraps from numbers import Number -from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, TypeVar, Union +from typing import Any, Awaitable, Callable, Dict, List, NoReturn, Optional, Tuple, TypeVar, Union import aiohttp import aiohttp.web_exceptions @@ -138,7 +138,7 @@ async def wrapped(request, userdata, *args, **kwargs): return await fun(request, userdata, *args, **kwargs) except asyncio.CancelledError: raise - except aiohttp.web_exceptions.HTTPFound as e: + except web.HTTPFound as e: raise e except Exception as e: if SCOPE == 'dev': @@ -1679,7 +1679,7 @@ async def ui_batch(request, userdata, batch_id): @check_csrf_token @web_billing_project_users_only(redirect=False) @catch_ui_error_in_dev -async def ui_cancel_batch(request: web.Request, _, batch_id: int) -> web.HTTPFound: +async def ui_cancel_batch(request: web.Request, _, batch_id: int) -> NoReturn: post = await request.post() q = post.get('q') params: Dict[str, str] = {} @@ -1691,14 +1691,14 @@ async def ui_cancel_batch(request: web.Request, _, batch_id: int) -> web.HTTPFou set_message(session, f'Batch {batch_id} cancelled.', 'info') finally: location = request.app.router['batches'].url_for().with_query(params) - return web.HTTPFound(location=location) # pylint: disable=lost-exception + raise web.HTTPFound(location=location) # pylint: disable=lost-exception @routes.post('/batches/{batch_id}/delete') @check_csrf_token @web_billing_project_users_only(redirect=False) @catch_ui_error_in_dev -async def ui_delete_batch(request: web.Request, _, batch_id: int) -> web.HTTPFound: +async def ui_delete_batch(request: web.Request, _, batch_id: int) -> NoReturn: post = await request.post() q = post.get('q') params: Dict[str, str] = {} @@ -1708,7 +1708,7 @@ async def ui_delete_batch(request: web.Request, _, batch_id: int) -> web.HTTPFou session = await aiohttp_session.get_session(request) set_message(session, f'Batch {batch_id} deleted.', 'info') location = request.app.router['batches'].url_for().with_query(params) - return web.HTTPFound(location=location) + raise web.HTTPFound(location=location) @routes.get('/batches', name='batches') @@ -2263,7 +2263,7 @@ async def post_edit_billing_limits(request: web.Request) -> web.Response: @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_edit_billing_limits_ui(request: web.Request, _) -> web.HTTPFound: +async def post_edit_billing_limits_ui(request: web.Request, _) -> NoReturn: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] post = await request.post() @@ -2273,7 +2273,7 @@ async def post_edit_billing_limits_ui(request: web.Request, _) -> web.HTTPFound: await _handle_ui_error(session, _edit_billing_limit, db, billing_project, limit) set_message(session, f'Modified limit {limit} for billing project {billing_project}.', 'info') # type: ignore finally: - return web.HTTPFound(deploy_config.external_url('batch', '/billing_limits')) # pylint: disable=lost-exception + raise web.HTTPFound(deploy_config.external_url('batch', '/billing_limits')) # pylint: disable=lost-exception async def _query_billing(request: web.Request, user: Optional[str] = None) -> Tuple[list, str, Optional[str]]: @@ -2489,7 +2489,7 @@ async def delete(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_billing_projects_remove_user(request: web.Request, _) -> web.HTTPFound: +async def post_billing_projects_remove_user(request: web.Request, _) -> NoReturn: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] user = request.match_info['user'] @@ -2499,7 +2499,7 @@ async def post_billing_projects_remove_user(request: web.Request, _) -> web.HTTP await _handle_ui_error(session, _remove_user_from_billing_project, db, billing_project, user) set_message(session, f'Removed user {user} from billing project {billing_project}.', 'info') finally: - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception + raise web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/users/{user}/remove') @@ -2559,7 +2559,7 @@ async def insert(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_billing_projects_add_user(request: web.Request, _) -> web.HTTPFound: +async def post_billing_projects_add_user(request: web.Request, _) -> NoReturn: db: Database = request.app['db'] post = await request.post() user = post['user'] @@ -2571,7 +2571,7 @@ async def post_billing_projects_add_user(request: web.Request, _) -> web.HTTPFou await _handle_ui_error(session, _add_user_to_billing_project, db, billing_project, user) set_message(session, f'Added user {user} to billing project {billing_project}.', 'info') # type: ignore finally: - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception + raise web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/users/{user}/add') @@ -2617,7 +2617,7 @@ async def insert(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_create_billing_projects(request: web.Request, _) -> web.HTTPFound: +async def post_create_billing_projects(request: web.Request, _) -> NoReturn: db: Database = request.app['db'] post = await request.post() billing_project = post['billing_project'] @@ -2627,7 +2627,7 @@ async def post_create_billing_projects(request: web.Request, _) -> web.HTTPFound await _handle_ui_error(session, _create_billing_project, db, billing_project) set_message(session, f'Added billing project {billing_project}.', 'info') # type: ignore finally: - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception + raise web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/create') @@ -2678,7 +2678,7 @@ async def close_project(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_close_billing_projects(request: web.Request, _) -> web.HTTPFound: +async def post_close_billing_projects(request: web.Request, _) -> NoReturn: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] @@ -2687,7 +2687,7 @@ async def post_close_billing_projects(request: web.Request, _) -> web.HTTPFound: await _handle_ui_error(session, _close_billing_project, db, billing_project) set_message(session, f'Closed billing project {billing_project}.', 'info') finally: - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception + raise web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/close') @@ -2723,7 +2723,7 @@ async def open_project(tx): @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) @catch_ui_error_in_dev -async def post_reopen_billing_projects(request, userdata): # pylint: disable=unused-argument +async def post_reopen_billing_projects(request: web.Request) -> NoReturn: db: Database = request.app['db'] billing_project = request.match_info['billing_project'] @@ -2732,7 +2732,7 @@ async def post_reopen_billing_projects(request, userdata): # pylint: disable=un await _handle_ui_error(session, _reopen_billing_project, db, billing_project) set_message(session, f'Re-opened billing project {billing_project}.', 'info') finally: - return web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception + raise web.HTTPFound(deploy_config.external_url('batch', '/billing_projects')) # pylint: disable=lost-exception @routes.post('/api/v1alpha/billing_projects/{billing_project}/reopen') @@ -2797,7 +2797,7 @@ async def _refresh(app): @routes.get('/') @auth.web_authenticated_users_only() @catch_ui_error_in_dev -async def index(request: web.Request, _) -> web.HTTPFound: +async def index(request: web.Request, _) -> NoReturn: location = request.app.router['batches'].url_for() raise web.HTTPFound(location=location) diff --git a/ci/ci/ci.py b/ci/ci/ci.py index 77bda23ba2e..d3112d9e6f9 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -4,7 +4,7 @@ import logging import os import traceback -from typing import Callable, Dict, List, Optional, Set, Tuple, TypedDict +from typing import Callable, Dict, List, NoReturn, Optional, Set, Tuple, TypedDict import aiohttp_session # type: ignore import kubernetes_asyncio @@ -222,11 +222,11 @@ async def retry_pr(wb, pr, request): @routes.post('/watched_branches/{watched_branch_index}/pr/{pr_number}/retry') @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) -async def post_retry_pr(request: web.Request, _) -> web.HTTPFound: +async def post_retry_pr(request: web.Request, _) -> NoReturn: wb, pr = wb_and_pr_from_request(request) await asyncio.shield(retry_pr(wb, pr, request)) - return web.HTTPFound(deploy_config.external_url('ci', f'/watched_branches/{wb.index}/pr/{pr.number}')) + raise web.HTTPFound(deploy_config.external_url('ci', f'/watched_branches/{wb.index}/pr/{pr.number}')) @routes.get('/batches') @@ -325,7 +325,7 @@ async def get_user(request: web.Request, userdata: UserData) -> web.Response: @routes.post('/authorize_source_sha') @check_csrf_token @auth.web_authenticated_developers_only(redirect=False) -async def post_authorized_source_sha(request: web.Request, _) -> web.HTTPFound: +async def post_authorized_source_sha(request: web.Request, _) -> NoReturn: app = request.app db: Database = app['db'] post = await request.post() @@ -334,7 +334,7 @@ async def post_authorized_source_sha(request: web.Request, _) -> web.HTTPFound: log.info(f'authorized sha: {sha}') session = await aiohttp_session.get_session(request) set_message(session, f'SHA {sha} authorized.', 'info') - return web.HTTPFound(deploy_config.external_url('ci', '/')) + raise web.HTTPFound(deploy_config.external_url('ci', '/')) @routes.get('/healthcheck') @@ -527,14 +527,14 @@ async def batch_callback(request): @routes.post('/freeze_merge_deploy') @check_csrf_token @auth.web_authenticated_developers_only() -async def freeze_deploys(request: web.Request, _) -> web.HTTPFound: +async def freeze_deploys(request: web.Request, _) -> NoReturn: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) if app['frozen_merge_deploy']: set_message(session, 'CI is already frozen.', 'info') - return web.HTTPFound(deploy_config.external_url('ci', '/')) + raise web.HTTPFound(deploy_config.external_url('ci', '/')) await db.execute_update( ''' @@ -546,20 +546,20 @@ async def freeze_deploys(request: web.Request, _) -> web.HTTPFound: set_message(session, 'Froze all merges and deploys.', 'info') - return web.HTTPFound(deploy_config.external_url('ci', '/')) + raise web.HTTPFound(deploy_config.external_url('ci', '/')) @routes.post('/unfreeze_merge_deploy') @check_csrf_token @auth.web_authenticated_developers_only() -async def unfreeze_deploys(request: web.Request, _) -> web.HTTPFound: +async def unfreeze_deploys(request: web.Request, _) -> NoReturn: app = request.app db: Database = app['db'] session = await aiohttp_session.get_session(request) if not app['frozen_merge_deploy']: set_message(session, 'CI is already unfrozen.', 'info') - return web.HTTPFound(deploy_config.external_url('ci', '/')) + raise web.HTTPFound(deploy_config.external_url('ci', '/')) await db.execute_update( ''' @@ -571,7 +571,7 @@ async def unfreeze_deploys(request: web.Request, _) -> web.HTTPFound: set_message(session, 'Unfroze all merges and deploys.', 'info') - return web.HTTPFound(deploy_config.external_url('ci', '/')) + raise web.HTTPFound(deploy_config.external_url('ci', '/')) @routes.get('/namespaces') @@ -600,7 +600,7 @@ async def get_active_namespaces(request: web.Request, userdata: UserData) -> web @routes.post('/namespaces/{namespace}/services/add') @check_csrf_token @auth.web_authenticated_developers_only() -async def add_namespaced_service(request: web.Request, _) -> web.HTTPFound: +async def add_namespaced_service(request: web.Request, _) -> NoReturn: db: Database = request.app['db'] post = await request.post() service = post['service'] @@ -623,13 +623,13 @@ async def add_namespaced_service(request: web.Request, _) -> web.HTTPFound: (namespace, service), ) - return web.HTTPFound(deploy_config.external_url('ci', '/namespaces')) + raise web.HTTPFound(deploy_config.external_url('ci', '/namespaces')) @routes.post('/namespaces/add') @check_csrf_token @auth.web_authenticated_developers_only() -async def add_namespace(request: web.Request, _) -> web.HTTPFound: +async def add_namespace(request: web.Request, _) -> NoReturn: db: Database = request.app['db'] post = await request.post() namespace = post['namespace'] @@ -648,7 +648,7 @@ async def add_namespace(request: web.Request, _) -> web.HTTPFound: (namespace,), ) - return web.HTTPFound(deploy_config.external_url('ci', '/namespaces')) + raise web.HTTPFound(deploy_config.external_url('ci', '/namespaces')) async def cleanup_expired_namespaces(db: Database): diff --git a/gear/gear/auth.py b/gear/gear/auth.py index 23f7537aff6..79057c4bd49 100644 --- a/gear/gear/auth.py +++ b/gear/gear/auth.py @@ -2,7 +2,7 @@ import logging import urllib.parse from functools import wraps -from typing import Awaitable, Callable, Optional, Tuple, TypedDict +from typing import Awaitable, Callable, NoReturn, Optional, Tuple, TypedDict import aiohttp import aiohttp_session @@ -73,7 +73,7 @@ async def wrapped(request: web.Request) -> web.StreamResponse: rest_userdata = await self._userdata_from_rest_request(request) if rest_userdata: raise web.HTTPUnauthorized(reason="provided REST auth to web endpoint") - raise _web_unauthenticated(request, redirect) + _web_unauthenticated(request, redirect) return await fun(request, userdata) return wrapped @@ -153,7 +153,7 @@ async def impersonate_user_and_get_info(session_id: str, client_session: httpx.C raise -def _web_unauthenticated(request, redirect): +def _web_unauthenticated(request, redirect) -> NoReturn: if not redirect: raise web.HTTPUnauthorized() @@ -168,4 +168,4 @@ def _web_unauthenticated(request, redirect): if x_forwarded_proto: request_url = request_url.with_scheme(x_forwarded_proto) - return web.HTTPFound(f'{login_url}?next={urllib.parse.quote(str(request_url))}') + raise web.HTTPFound(f'{login_url}?next={urllib.parse.quote(str(request_url))}') diff --git a/hail/python/hailtop/config/deploy_config.py b/hail/python/hailtop/config/deploy_config.py index f8da8534918..1bf87ad8052 100644 --- a/hail/python/hailtop/config/deploy_config.py +++ b/hail/python/hailtop/config/deploy_config.py @@ -123,12 +123,12 @@ def prefix_application(self, app, service, **kwargs): root_routes = web.RouteTableDef() @root_routes.get('/healthcheck') - async def get_healthcheck(request): # pylint: disable=unused-argument,unused-variable + async def get_healthcheck(_): return web.Response() @root_routes.get('/metrics') - async def get_metrics(request): # pylint: disable=unused-argument,unused-variable - return web.HTTPFound(location=f'{base_path}/metrics') + async def get_metrics(_): + raise web.HTTPFound(location=f'{base_path}/metrics') root_app = web.Application(**kwargs) root_app.add_routes(root_routes) diff --git a/notebook/notebook/notebook.py b/notebook/notebook/notebook.py index 0f5603741a7..0f7d3cd5f3a 100644 --- a/notebook/notebook/notebook.py +++ b/notebook/notebook/notebook.py @@ -84,7 +84,7 @@ def wrap(fun): async def wrapped(request, userdata, *args, **kwargs): if not userdata: if redirect: - return web.HTTPFound(deploy_config.external_url('workshop', '/login')) + raise web.HTTPFound(deploy_config.external_url('workshop', '/login')) raise web.HTTPUnauthorized() return await fun(request, userdata, *args, **kwargs) @@ -328,7 +328,7 @@ async def _post_notebook(service, request, userdata): (user_id, user_id, notebook_token, pod.metadata.name, state, pod.status.pod_ip, jupyter_token), ) - return web.HTTPFound(location=deploy_config.external_url(service, '/notebook')) + raise web.HTTPFound(location=deploy_config.external_url(service, '/notebook')) async def _delete_notebook(service, request, userdata): @@ -343,7 +343,7 @@ async def _delete_notebook(service, request, userdata): async with conn.cursor() as cursor: await cursor.execute('DELETE FROM notebooks WHERE user_id = %s;', user_id) - return web.HTTPFound(location=deploy_config.external_url(service, '/notebook')) + raise web.HTTPFound(location=deploy_config.external_url(service, '/notebook')) async def _wait_websocket(service, request, userdata): @@ -396,7 +396,7 @@ async def _wait_websocket(service, request, userdata): async def _get_error(service, request, userdata): if not userdata: - return web.HTTPFound(deploy_config.external_url(service, '/login')) + raise web.HTTPFound(deploy_config.external_url(service, '/login')) app = request.app k8s = app['k8s_client'] @@ -412,7 +412,7 @@ async def _get_error(service, request, userdata): session = await aiohttp_session.get_session(request) if notebook: if new_status['state'] == 'Ready': - return web.HTTPFound( + raise web.HTTPFound( deploy_config.external_url( service, f'/instance/{notebook["notebook_token"]}/?token={notebook["jupyter_token"]}' ) @@ -424,7 +424,7 @@ async def _get_error(service, request, userdata): ) else: set_message(session, 'Jupyter instance not found. Please launch a new instance.', 'error') - return web.HTTPFound(deploy_config.external_url(service, '/notebook')) + raise web.HTTPFound(deploy_config.external_url(service, '/notebook')) async def _get_auth(request, userdata): @@ -538,7 +538,7 @@ async def create_workshop(request, userdata): # pylint: disable=unused-argument else: raise - return web.HTTPFound(deploy_config.external_url('notebook', '/workshop-admin')) + raise web.HTTPFound(deploy_config.external_url('notebook', '/workshop-admin')) @routes.post('/workshop-admin-update') @@ -571,7 +571,7 @@ async def update_workshop(request, userdata): # pylint: disable=unused-argument else: set_message(session, f'Updated workshop {name}.', 'info') - return web.HTTPFound(deploy_config.external_url('notebook', '/workshop-admin')) + raise web.HTTPFound(deploy_config.external_url('notebook', '/workshop-admin')) @routes.post('/workshop-admin-delete') @@ -598,7 +598,7 @@ async def delete_workshop(request, userdata): # pylint: disable=unused-argument else: set_message(session, f'Workshop {name} not found.', 'error') - return web.HTTPFound(deploy_config.external_url('notebook', '/workshop-admin')) + raise web.HTTPFound(deploy_config.external_url('notebook', '/workshop-admin')) workshop_routes = web.RouteTableDef() @@ -616,7 +616,7 @@ async def workshop_get_index(request, userdata): @web_maybe_authenticated_workshop_guest async def workshop_get_login(request, userdata): if userdata: - return web.HTTPFound(location=deploy_config.external_url('workshop', '/notebook')) + raise web.HTTPFound(location=deploy_config.external_url('workshop', '/notebook')) page_context = {'notebook_service': 'workshop'} return await render_template('workshop', request, userdata, 'workshop/login.html', page_context) @@ -646,7 +646,7 @@ async def workshop_post_login(request): if len(workshops) != 1: assert len(workshops) == 0 set_message(session, 'Workshop Inactive!', 'error') - return web.HTTPFound(location=deploy_config.external_url('workshop', '/login')) + raise web.HTTPFound(location=deploy_config.external_url('workshop', '/login')) workshop = workshops[0] # use hex since K8s labels can't start or end with _ or - @@ -655,7 +655,7 @@ async def workshop_post_login(request): set_message(session, f'Welcome to the {name} workshop!', 'info') - return web.HTTPFound(location=deploy_config.external_url('workshop', '/notebook')) + raise web.HTTPFound(location=deploy_config.external_url('workshop', '/notebook')) @workshop_routes.post('/logout') @@ -679,7 +679,7 @@ async def workshop_post_logout(request, userdata): if 'workshop_session' in session: del session['workshop_session'] - return web.HTTPFound(location=deploy_config.external_url('workshop', '/notebook')) + raise web.HTTPFound(location=deploy_config.external_url('workshop', '/notebook')) @workshop_routes.get('/resources') From 8fb7d90fe89bbd7309a0260bf755780cc43cec6a Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Tue, 15 Aug 2023 20:52:46 -0400 Subject: [PATCH 110/180] [compiler] fix TableUnion lowering (#13414) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #13407 CHANGELOG: Resolves #13407 in which uses of `union_rows` could reduce parallelism to one partition resulting in severely degraded performance. TableUnion was always collapsing to a single partition when the key was empty. This adds a special case handling, which just concatenates partitions. The body of the resulting TableStage is a little hacky: it does a StreamMultiMerge, but where exactly one input stream is non-empty. I think that should have fine performance, and I didn’t see any simpler ways to do it. --- hail/python/test/hail/table/test_table.py | 16 ++-- .../hail/expr/ir/lowering/LowerTableIR.scala | 76 +++++++++++++++---- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/hail/python/test/hail/table/test_table.py b/hail/python/test/hail/table/test_table.py index 4b55bdfd60c..92b8c28daf0 100644 --- a/hail/python/test/hail/table/test_table.py +++ b/hail/python/test/hail/table/test_table.py @@ -1054,17 +1054,19 @@ def test_localize_self_join(self): self.assertTrue(t._same(ref_tab)) def test_union(self): - t1 = hl.utils.range_table(5) + t1 = hl.utils.range_table(5, 2) - t2 = hl.utils.range_table(5) - t2 = t2.key_by(idx = t2.idx + 5) + t2 = hl.utils.range_table(5, 2) + t2 = t2.key_by(idx=t2.idx + 5) - t3 = hl.utils.range_table(5) - t3 = t3.key_by(idx = t3.idx + 10) + t3 = hl.utils.range_table(5, 2) + t3 = t3.key_by(idx=t3.idx + 10) self.assertTrue(t1.union(t2, t3)._same(hl.utils.range_table(15))) - self.assertTrue(t1.key_by().union(t2.key_by(), t3.key_by()) - ._same(hl.utils.range_table(15).key_by())) + + no_key = t1.key_by().union(t2.key_by(), t3.key_by()) + assert no_key.n_partitions() == 6 + self.assertTrue(no_key._same(hl.utils.range_table(15).key_by())) def nested_union(self, N, M): t = hl.utils.range_table(N, n_partitions=1) diff --git a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala index d6bbfd263c8..8cc95c205e8 100644 --- a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala +++ b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala @@ -3,7 +3,7 @@ package is.hail.expr.ir.lowering import is.hail.HailContext import is.hail.backend.ExecuteContext import is.hail.expr.ir.ArrayZipBehavior.AssertSameLength -import is.hail.expr.ir.functions.{TableCalculateNewPartitions, WrappedMatrixToTableFunction} +import is.hail.expr.ir.functions.{ArrayFunctions, TableCalculateNewPartitions, WrappedMatrixToTableFunction} import is.hail.expr.ir.{TableNativeWriter, agg, _} import is.hail.io.{BufferSpec, TypedCodecSpec} import is.hail.methods.{ForceCountTable, LocalLDPrune, NPartitionsTable, TableFilterPartitions} @@ -54,6 +54,47 @@ object TableStage { def wrapInBindings(body: IR, letBindings: IndexedSeq[(String, IR)]): IR = letBindings.foldRight[IR](body) { case ((name, value), body) => Let(name, value, body) } + + def concatenate(ctx: ExecuteContext, children: IndexedSeq[TableStage]): TableStage = { + val keyType = children.head.kType + assert(keyType.size == 0) + assert(children.forall(_.kType == keyType)) + + val ctxType = TTuple(children.map(_.ctxType): _*) + val ctxArrays = children.view.zipWithIndex.map { case (child, idx) => + ToArray(mapIR(child.contexts) { ctx => + MakeTuple.ordered(children.indices.map { idx2 => + if (idx == idx2) ctx else NA(children(idx2).ctxType) + }) + }) + } + val ctxs = flatMapIR(MakeStream(ctxArrays.toFastIndexedSeq, TStream(TArray(ctxType)))) { ctxArray => + ToStream(ctxArray) + } + + val newGlobals = children.head.globals + val globalsRef = Ref(genUID(), newGlobals.typ) + val newPartitioner = new RVDPartitioner(ctx.stateManager, keyType, children.flatMap(_.partitioner.rangeBounds)) + + TableStage( + children.flatMap(_.letBindings) :+ globalsRef.name -> newGlobals, + children.flatMap(_.broadcastVals) :+ globalsRef.name -> globalsRef, + globalsRef, + newPartitioner, + TableStageDependency.union(children.map(_.dependency)), + ctxs, + (ctxRef: Ref) => { + StreamMultiMerge( + children.indices.map { i => + bindIR(GetTupleElement(ctxRef, i)) { ctx => + If(IsNA(ctx), + MakeStream(IndexedSeq(), TStream(children(i).rowType)), + children(i).partition(ctx)) + } + }, + IndexedSeq()) + }) + } } // Scope structure: @@ -1542,21 +1583,26 @@ object LowerTableIR { case x@TableUnion(children) => val lowered = children.map(lower) val keyType = x.typ.keyType - val newPartitioner = RVDPartitioner.generate(ctx.stateManager, keyType, lowered.flatMap(_.partitioner.rangeBounds)) - val repartitioned = lowered.map(_.repartitionNoShuffle(ctx, newPartitioner)) - TableStage( - repartitioned.flatMap(_.letBindings), - repartitioned.flatMap(_.broadcastVals), - repartitioned.head.globals, - newPartitioner, - TableStageDependency.union(repartitioned.map(_.dependency)), - zipIR(repartitioned.map(_.contexts), ArrayZipBehavior.AssumeSameLength) { ctxRefs => - MakeTuple.ordered(ctxRefs) - }, - ctxRef => - StreamMultiMerge(repartitioned.indices.map(i => repartitioned(i).partition(GetTupleElement(ctxRef, i))), keyType.fieldNames) - ) + if (keyType.size == 0) { + TableStage.concatenate(ctx, lowered) + } else { + val newPartitioner = RVDPartitioner.generate(ctx.stateManager, keyType, lowered.flatMap(_.partitioner.rangeBounds)) + val repartitioned = lowered.map(_.repartitionNoShuffle(ctx, newPartitioner)) + + TableStage( + repartitioned.flatMap(_.letBindings), + repartitioned.flatMap(_.broadcastVals), + repartitioned.head.globals, + newPartitioner, + TableStageDependency.union(repartitioned.map(_.dependency)), + zipIR(repartitioned.map(_.contexts), ArrayZipBehavior.AssumeSameLength) { ctxRefs => + MakeTuple.ordered(ctxRefs) + }, + ctxRef => + StreamMultiMerge(repartitioned.indices.map(i => repartitioned(i).partition(GetTupleElement(ctxRef, i))), keyType.fieldNames) + ) + } case x@TableMultiWayZipJoin(children, fieldName, globalName) => val lowered = children.map(lower) From 7b65bf9eae88b8dd6f1486b8480599b78296da22 Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 15 Aug 2023 22:05:34 -0400 Subject: [PATCH 111/180] [prometheus] update to 2.46.0 to attempt to avoid WAL issues (#13443) --- prometheus/prometheus.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prometheus/prometheus.yaml b/prometheus/prometheus.yaml index 0f3acbe463a..e290d054153 100644 --- a/prometheus/prometheus.yaml +++ b/prometheus/prometheus.yaml @@ -288,7 +288,7 @@ spec: fsGroup: 65534 containers: - name: prometheus - image: prom/prometheus:v2.34.0 + image: prom/prometheus:v2.46.0 imagePullPolicy: Always command: - "/bin/prometheus" From 923775899d2f0a27a0d840e3f4fbfc446ea653fd Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 15 Aug 2023 23:11:12 -0400 Subject: [PATCH 112/180] [ci] Make dev namespace scaling cron in UTC (#13429) GCP k8s crons are in UTC apparently. We could instead specify a timezone here, LMK which you prefer. --- build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.yaml b/build.yaml index a7022b4e22d..3398e8a597b 100644 --- a/build.yaml +++ b/build.yaml @@ -3702,7 +3702,7 @@ steps: name: dev-namespace-scaledown-{{ user["username"] }} namespace: {{ user["username"] }} spec: - schedule: "0 20 * * 1,2,3,4,5" # Weekdays at 8p + schedule: "0 0 * * 1,2,3,4,5" # Weekdays at midnight UTC concurrencyPolicy: Forbid successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 1 @@ -3726,7 +3726,7 @@ steps: name: dev-namespace-scaleup-{{ user["username"] }} namespace: {{ user["username"] }} spec: - schedule: "0 9 * * 1,2,3,4,5" # Weekdays at 9a + schedule: "0 13 * * 1,2,3,4,5" # Weekdays at 1pm UTC concurrencyPolicy: Forbid successfulJobsHistoryLimit: 0 failedJobsHistoryLimit: 1 From b62647af006f4fe2fa81746aaeb92e93839e9921 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 16 Aug 2023 16:06:50 -0400 Subject: [PATCH 113/180] [dev-docs] Update dev docs for using dev namespaces (#13449) cc: @sjparsa --- dev-docs/development_process.md | 118 +++++++++++++++++++++++++++----- dev-docs/ksync.md | 102 --------------------------- 2 files changed, 99 insertions(+), 121 deletions(-) delete mode 100644 dev-docs/ksync.md diff --git a/dev-docs/development_process.md b/dev-docs/development_process.md index e845f9dfdb7..c6eee75ebd4 100644 --- a/dev-docs/development_process.md +++ b/dev-docs/development_process.md @@ -29,7 +29,7 @@ develop effectively. Hail currently supports Python version 3.9 or greater. -``` +```bash make install-dev-requirements ``` @@ -37,7 +37,7 @@ to install the full set of python dependencies across the Hail repo. To make sure that certain formatting requirements are caught early, run -``` +```bash pre-commit install --install-hooks ``` @@ -50,7 +50,7 @@ Sometimes large formatting or refactoring commits can muddle the git history for a file. If your change is one of these, follow up by adding the commit SHA to `.git-blame-ignore-revs`. To configure `git blame` to ignore these commits, run -``` +```bash git config blame.ignoreRevsFile $HAIL/.git-blame-ignore-revs ``` @@ -62,7 +62,7 @@ Install and configure tools necessary for working on the Hail Services: 2. Install [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/), if not already installed. (To test installation, run `kubectl` in a terminal window) 3. Install [`gcloud`](https://cloud.google.com/sdk/docs/install) 4. Configure gcloud and Docker for Hail: -``` +```bash gcloud auth login gcloud config set project hail-vdc gcloud container clusters get-credentials vdc --zone=us-central1-a @@ -76,19 +76,20 @@ export DOCKER_BUILDKIT=1 # Shell utilities for managing the Hail kubernetes cluster source /path/to/hail-repository/devbin/functions.sh ``` + 6. Run `brew install fswatch` ### Testing / Debugging There are different strategies for debugging depending on whether you are working on a compiler project or a services project. -#### Compiler: +#### Compiler For a compiler project, you can build and run the tests locally on your computer. To build hail for development purposes, you should run the following command in the hail/hail directory: -``` +```bash make install-editable ``` @@ -96,43 +97,122 @@ There are tests written in Python and tests written in Scala. For the python tests, we use pytest. -#### Services: +#### Services + +Production, test and development versions of Hail Batch share one Kubernetes +cluster, but are able to coexist without interference because they are isolated +in different [namespaces](https://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/). +The different kinds of namespaces are: + +- The `default` namespace. This is where Production lives. +- Test namespaces. These are ephemeral namespaces used to test PRs. Every CI + pipeline for a PR creates a namespace and deletes it when the tests finish. +- Dev namespaces. These are long-lived namespaces for developing new features. + Each developer has their own namespace. It's name is the same as the developer's + hail username. For a services project, you can push your branch to GitHub and then run what we -call “dev deploy”. The command to invoke this is +call a “dev deploy”. The command to invoke a dev deploy is -``` -hailctl dev deploy -b /hail: -s ,,... +```bash +HAIL_DEFAULT_NAMESPACE=default hailctl dev deploy -b /hail: -s ,,... ``` Dev deploy creates a batch that deploys the build steps specified by the `-s` in -your own Kubernetes namespace, MySQL database. For example, if we want to test +your Kubernetes dev namespace. For example, if we want to test whether the Batch tests still pass, we would specify -s test_batch. This will run all the dependent steps for testing Batch such as creating credentials, a live Auth service, a MySQL database for Batch, and a live Batch deployment. -Your namespace name is the same as your username. + Submitting a dev deploy with hailctl will give you the link to a UI where you can monitor the progress of everything deploying and get the logs for any steps that fail. You can also see a recent history of your dev deploys at [ci.hail.is/me](https://ci.hail.is/me). +The first time a namespace is used, the Auth service in that namespace won't +have any users. In order submit jobs to the namespace, make sure to include +the `add_developers` step to the dev deploy. So a first dev deploy might look like: -If the tests fail, you can then examine the Kubernetes logs for the service -using something like +```bash +HAIL_DEFAULT_NAMESPACE=default hailctl dev deploy -b /hail: -s deploy_batch,add_developers +``` +After this dev deploy completes, you should be able to access your namespace +by navigating to https://internal.hail.is//batch. + +To submit jobs to your dev namespace, you need to configure your local hail +installation to point to the dev namespace. You can do this by running + +```bash +hailctl dev config set default_namespace +hailctl auth login ``` +Then, any Hail Batch or Query-on-Batch script will submit to your dev namespace. + +You can also use the `HAIL_DEFAULT_NAMESPACE` environment variable to alter +the namespace for individual terminal sessions or commands. + +NOTE: The dev deploy command above sets `HAIL_DEFAULT_NAMESPACE=default`. That's +because `hailctl dev deploy` submits a request to the production CI service that +lives in the `default` namespace. This does *not* mean that your branch will be deployed +to the `default` namespace, it will always be deployed into your dev namespace. + +To examine the Kubernetes logs for the service in your namespace, use something like + +```bash kubectl -n logs -l app=batch-driver --tail=999999 | less ``` -To check the MySQL database, you first need to find the name of the specific pod -running an “admin-pod” and then log into that pod: +To check the MySQL database in your namespace, you can log in to the database +pod like so: ``` -kubectl -n get pods -l app=admin-pod -kubectl -n exec -it /bin/bash +kubectl -n exec -it db-0 /bin/bash $ mysql ``` +##### Alternatives to dev deploy + +There are three ways to deploy code into a dev namespace: +1. dev deploy +2. make deploy +3. sync.py + +These are listed in order of broadest scope to narrowest scope, so it is never +wrong to do something higher on the list, but it might be a slower feedback loop. + +A dev deploy is necessary under the following conditions: +- A dev namespace has not been used before +- You have added a migration that must be run against a service's database +- Not all necessary services (like Auth) are deployed in the namespace and you + do not want to `make` deploy them individually. + +If you just want to redeploy a single service, you can do so with the following: + +```bash +make -C batch deploy NAMESPACE= +``` + +If you only want to make a Python code change to an already-running service +in Kubernetes, you can run `devbin/sync.py` like the following: + +```bash +python3 devbin/sync.py \ + --namespace \ + --app batch --app batch-driver \ + --path batch/batch /usr/local/lib/python3.9/dist-packages/ \ + --path gear/gear /usr/local/lib/python3.9/dist-packages/ \ + --path web_common/web_common /usr/local/lib/python3.9/dist-packages/ \ + --path hail/python/hailtop /usr/local/lib/python3.9/dist-packages/ +``` + +This will create a long-running process that watches the files in the `batch` +and `gear` modules. When changes to those files are saved it will upload those +changes to currently running pods in the namespace and restart those pods. Note +that Batch Workers are not running as pods in Kubernetes, and are immutable. So +if you want to update code running on a Batch Worker, you will need to `make` +deploy and then delete existing workers in your namespace. + ## PR Once you have a branch that you are happy with, then you create a Pull Request @@ -232,7 +312,7 @@ retry strategy. If a Batch database migration is involved in the PR, then we’ll need to wait for the database to be migrated and then redeploy the Batch service by hand using -``` +```bash make -c batch deploy ``` diff --git a/dev-docs/ksync.md b/dev-docs/ksync.md deleted file mode 100644 index 9cfcda478be..00000000000 --- a/dev-docs/ksync.md +++ /dev/null @@ -1,102 +0,0 @@ -# ksync - -https://github.com/ksync/ksync - -## Installation - -``` -curl https://ksync.github.io/gimme-that/gimme.sh | bash -``` - -## Setting it up on hail-vdc - -This only needs to be done once on a cluster. - -1. First make sure you have a cluster admin role - -``` -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: is-cluster-admin -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: -- apiGroup: rbac.authorization.k8s.io - kind: User - name: -``` - -Apply this config to the cluster. - -2. Run ksync init - -``` -ksync init --context gke_hail-vdc_us-central1-a_vdc -``` - -3. Add a toleration to the ksync daemon set that has been created in the kube-system namespace - -``` -kubectl -n kube-system patch daemonset ksync --type merge -p ' -{ - "spec": { - "template": { - "spec": { - "tolerations": [ - { - "effect": "NoSchedule", - "key": "preemptible", - "operator": "Equal", - "value": "true" - } - ] - } - } - } -} -' -``` - -4. Check the ksync pods are running - -``` -kubectl -n kube-system get pods -l app=ksync -``` - -## Setting it up locally - -1. Run ksync watch in a new terminal window - -``` -ksync watch -``` - -2. Make sure app is deployed in the namespace you want (dev deploy) - -3. Create a spec in ~/.ksync/ksync.yaml using the create operation - -``` -ksync create --local-read-only -l app=auth --name - -n jigold $(pwd)// /usr/local/lib/python3.9/dist-packages// -``` - -4. Use ksync get to make sure the pods are being watched - -``` -ksync get -``` - -5. When you're done syncing, kill the process with ksync watch - -6. To remove a spec to watch, run the delete command - -``` -ksync delete - -``` - -## Notes - -- ksync is updating all pods specified in ~/.ksync/ksync.yaml -when it is running (`ksync watch`) From bfdd53e9385bd7e7353fcf78e9eed01f52414e20 Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Wed, 16 Aug 2023 19:48:37 -0400 Subject: [PATCH 114/180] [query] force `aggregate_cols` to be local (#13405) CHANGELOG: MatrixTable.aggregate_cols no longer forces a distributed computation. This should be what you want in the majority of cases. In case you know the aggregation is very slow and should be parallelized, use mt.cols().aggregate instead. Most of the time, `aggregate_cols` will be much faster performing the aggregation locally. Currently, we generate a `TableAggregate` over a `TableParallelize` of the columns. We shouldn't try to optimize that to a local computation during compilation; `TableParallelize` should express the intent that the computation is expensive and really should be parallelized. This should be considered part of the semantics the compiler must preserve. This PR changes `aggregate_cols` to explicitly generate a local computation using `StreamAgg` (which was only exposed in Python relatively recently, which is why we haven't made this change sooner). Longer term, aggregating columns should probably get its own IR node, especially once we start partitioning along columns. --- hail/python/hail/ir/ir.py | 3 --- hail/python/hail/matrixtable.py | 22 +++++++++++++++---- .../hail/matrixtable/test_matrix_table.py | 11 ++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/hail/python/hail/ir/ir.py b/hail/python/hail/ir/ir.py index b2fa9f51658..a013f00c45f 100644 --- a/hail/python/hail/ir/ir.py +++ b/hail/python/hail/ir/ir.py @@ -2228,9 +2228,6 @@ def renderable_bindings(self, i, default_value=None): else: return {} - def renderable_uses_agg_context(self, i: int): - return i == 0 - def renderable_new_block(self, i: int) -> bool: return i == 1 diff --git a/hail/python/hail/matrixtable.py b/hail/python/hail/matrixtable.py index 6baceae5d33..496293897bf 100644 --- a/hail/python/hail/matrixtable.py +++ b/hail/python/hail/matrixtable.py @@ -2223,14 +2223,28 @@ def aggregate_cols(self, expr, _localize=True) -> Any: """ base, _ = self._process_joins(expr) analyze('MatrixTable.aggregate_cols', expr, self._global_indices, {self._col_axis}) - cols_table = ir.MatrixColsTable(base._mir) - subst_query = ir.subst(expr._ir, {}, {'sa': ir.Ref('row', cols_table.typ.row_type)}) - agg_ir = ir.TableAggregate(cols_table, subst_query) + cols_field = Env.get_uid() + globals = base.localize_entries(columns_array_field_name=cols_field).index_globals() + if len(self._col_key) == 0: + cols = globals[cols_field] + else: + if Env.hc()._warn_cols_order: + warning("aggregate_cols(): Aggregates over cols ordered by 'col_key'." + "\n To preserve matrix table column order, " + "first unkey columns with 'key_cols_by()'") + Env.hc()._warn_cols_order = False + cols = hl.sorted(globals[cols_field], key=lambda x: x.select(*self._col_key.keys())) + + agg_ir = ir.Let( + 'global', + globals.drop(cols_field)._ir, + ir.StreamAgg(ir.ToStream(cols._ir), 'sa', expr._ir)) + if _localize: return Env.backend().execute(ir.MakeTuple([agg_ir]))[0] else: - return construct_expr(ir.LiftMeOut(agg_ir), expr.dtype) + return construct_expr(agg_ir, expr.dtype) @typecheck_method(expr=expr_any, _localize=bool) def aggregate_entries(self, expr, _localize=True): diff --git a/hail/python/test/hail/matrixtable/test_matrix_table.py b/hail/python/test/hail/matrixtable/test_matrix_table.py index eaad844c746..544d0f73445 100644 --- a/hail/python/test/hail/matrixtable/test_matrix_table.py +++ b/hail/python/test/hail/matrixtable/test_matrix_table.py @@ -204,10 +204,21 @@ def test_aggregate_cols(self): qs = mt.aggregate_cols(agg.count()) self.assertEqual(qs, 100) + qs = hl.eval(mt.aggregate_cols(agg.count(), _localize=False)) + self.assertEqual(qs, 100) mt.aggregate_cols(hl.Struct(x=agg.collect(mt.s), y=agg.collect(mt.y1))) + def test_aggregate_cols_order(self): + path = new_temp_file(extension='mt') + mt = hl.utils.range_matrix_table(3, 3) + mt = mt.choose_cols([2, 1, 0]) + mt = mt.checkpoint(path) + assert mt.aggregate_cols(hl.agg.collect(mt.col_idx)) == [0, 1, 2] + mt = mt.key_cols_by() + assert mt.aggregate_cols(hl.agg.collect(mt.col_idx)) == [2, 1, 0] + def test_aggregate_entries(self): mt = self.get_mt() From 14d6f9aa8d2a9920f755dd10734583640097f39d Mon Sep 17 00:00:00 2001 From: jigold Date: Thu, 17 Aug 2023 11:52:17 -0400 Subject: [PATCH 115/180] [aioclient] Refactor BatchBuilder submit for ease of job groups changes (#13448) This should be just a simple refactoring in anticipation of having bunches for job groups as well. --- hail/python/hailtop/batch_client/aioclient.py | 153 ++++++++++-------- 1 file changed, 84 insertions(+), 69 deletions(-) diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index 33dc40eddd2..e8191c1e1c9 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -641,7 +641,8 @@ def _create_job(self, self._jobs.append(j) return j - async def _create_fast(self, byte_job_specs: List[bytes], n_jobs: int, progress_task: BatchProgressBarTask) -> Batch: + async def _create_fast(self, byte_job_specs: List[bytes], n_jobs: int, job_progress_task: BatchProgressBarTask) -> Batch: + assert not self._batch assert n_jobs == len(self._job_specs) b = bytearray() b.extend(b'{"bunch":') @@ -659,15 +660,16 @@ async def _create_fast(self, byte_job_specs: List[bytes], n_jobs: int, progress_ data=aiohttp.BytesPayload(b, content_type='application/json', encoding='utf-8'), ) batch_json = await resp.json() - progress_task.update(n_jobs) + job_progress_task.update(n_jobs) return Batch(self._client, batch_json['id'], self.attributes, self.token, submission_info=BatchSubmissionInfo(True)) - async def _update_fast(self, byte_job_specs: List[bytes], progress_task: BatchProgressBarTask) -> int: + async def _update_fast(self, byte_job_specs: List[bytes], n_jobs: int, job_progress_task: BatchProgressBarTask) -> int: assert self._batch + assert n_jobs == len(self._job_specs) b = bytearray() b.extend(b'{"bunch":') b.append(ord('[')) @@ -684,9 +686,43 @@ async def _update_fast(self, byte_job_specs: List[bytes], progress_task: BatchPr data=aiohttp.BytesPayload(b, content_type='application/json', encoding='utf-8'), ) update_json = await resp.json() - progress_task.update(len(byte_job_specs)) + job_progress_task.update(n_jobs) return int(update_json['start_job_id']) + def _create_bunches(self, + specs: List[dict], + max_bunch_bytesize: int, + max_bunch_size: int, + ) -> Tuple[List[List[bytes]], List[int]]: + assert max_bunch_bytesize > 0 + assert max_bunch_size > 0 + byte_specs = [orjson.dumps(spec) for spec in specs] + byte_specs_bunches: List[List[bytes]] = [] + bunch_sizes = [] + bunch: List[bytes] = [] + bunch_n_bytes = 0 + bunch_n_jobs = 0 + for spec in byte_specs: + n_bytes = len(spec) + assert n_bytes < max_bunch_bytesize, ( + 'every spec must be less than max_bunch_bytesize,' + f' { max_bunch_bytesize }B, but {spec.decode()} is larger') + if bunch_n_bytes + n_bytes < max_bunch_bytesize and len(bunch) < max_bunch_size: + bunch.append(spec) + bunch_n_bytes += n_bytes + bunch_n_jobs += 1 + else: + byte_specs_bunches.append(bunch) + bunch_sizes.append(bunch_n_jobs) + bunch = [spec] + bunch_n_bytes = n_bytes + bunch_n_jobs = 1 + if bunch: + byte_specs_bunches.append(bunch) + bunch_sizes.append(bunch_n_jobs) + + return (byte_specs_bunches, bunch_sizes) + async def _submit_jobs(self, batch_id: int, update_id: int, byte_job_specs: List[bytes], n_jobs: int, progress_task: BatchProgressBarTask): assert len(byte_job_specs) > 0, byte_job_specs @@ -743,56 +779,65 @@ async def _commit_update(self, batch_id: int, update_id: int) -> int: commit_json = await (await self._client._patch(f'/api/v1alpha/batches/{batch_id}/updates/{update_id}/commit')).json() return int(commit_json['start_job_id']) - MAX_BUNCH_BYTESIZE = 1024 * 1024 - MAX_BUNCH_SIZE = 1024 + async def _submit_job_bunches(self, + byte_job_specs_bunches: List[List[bytes]], + bunch_sizes: List[int], + progress_task: BatchProgressBarTask): + assert self._batch + await bounded_gather( + *[functools.partial(self._submit_jobs, self._batch.id, self._update_id, bunch, size, progress_task) + for bunch, size in zip(byte_job_specs_bunches, bunch_sizes) + ], + parallelism=6, + ) + + async def _submit(self, + max_bunch_bytesize: int, + max_bunch_size: int, + disable_progress_bar: bool, + min_bunches_for_progress_bar: Optional[int], + progress: BatchProgressBar) -> Optional[int]: + n_jobs = len(self._jobs) + byte_job_specs_bunches, job_bunch_sizes = self._create_bunches(self._job_specs, max_bunch_bytesize, max_bunch_size) + n_job_bunches = len(byte_job_specs_bunches) - async def _submit_bunches(self, - byte_job_specs_bunches: List[List[bytes]], - bunch_sizes: List[int], - progress: BatchProgressBar, - disable_progress_bar: bool): - with progress.with_task('submit bunches', total=len(self._job_specs), disable=disable_progress_bar) as progress_task: - n_bunches = len(byte_job_specs_bunches) + if min_bunches_for_progress_bar is not None and n_job_bunches < 100: + progress.progress.disable = True + + with progress.with_task('submit job bunches', total=n_jobs, disable=disable_progress_bar) as job_progress_task: if self._batch is None: - if n_bunches == 0: + if n_job_bunches == 0: self._batch = await self._open_batch() log.info(f'created batch {self._batch.id}') - return self._batch - if n_bunches == 1: - self._batch = await self._create_fast(byte_job_specs_bunches[0], bunch_sizes[0], progress_task) + return None + if n_job_bunches == 1: + self._batch = await self._create_fast(byte_job_specs_bunches[0], job_bunch_sizes[0], job_progress_task) start_job_id = 1 else: self._batch = await self._open_batch() assert self._update_id is not None - await bounded_gather( - *[functools.partial(self._submit_jobs, self._batch.id, self._update_id, bunch, size, progress_task) - for bunch, size in zip(byte_job_specs_bunches, bunch_sizes) - ], - parallelism=6, - ) + await self._submit_job_bunches(byte_job_specs_bunches, job_bunch_sizes, job_progress_task) start_job_id = await self._commit_update(self._batch.id, self._update_id) self._batch.submission_info.used_fast_update[self._update_id] = False assert start_job_id == 1 log.info(f'created batch {self._batch.id}') else: - if n_bunches == 0: + if n_job_bunches == 0: log.warning('Tried to submit an update with 0 jobs. Doing nothing.') - return self._batch - if n_bunches == 1: - start_job_id = await self._update_fast(byte_job_specs_bunches[0], progress_task) + return None + if n_job_bunches == 1: + start_job_id = await self._update_fast(byte_job_specs_bunches[0], job_bunch_sizes[0], job_progress_task) else: self._update_id = await self._create_update(self._batch.id) - await bounded_gather( - *[functools.partial(self._submit_jobs, self._batch.id, self._update_id, bunch, size, progress_task) - for bunch, size in zip(byte_job_specs_bunches, bunch_sizes) - ], - parallelism=6, - ) + await self._submit_job_bunches(byte_job_specs_bunches, job_bunch_sizes, job_progress_task) start_job_id = await self._commit_update(self._batch.id, self._update_id) self._batch.submission_info.used_fast_update[self._update_id] = False log.info(f'updated batch {self._batch.id}') return start_job_id + MAX_BUNCH_BYTESIZE = 1024 * 1024 + MAX_BUNCH_SIZE = 1024 + async def submit(self, max_bunch_bytesize: int = MAX_BUNCH_BYTESIZE, max_bunch_size: int = MAX_BUNCH_SIZE, @@ -802,47 +847,17 @@ async def submit(self, ) -> Batch: assert max_bunch_bytesize > 0 assert max_bunch_size > 0 - byte_job_specs = [orjson.dumps(job_spec) - for job_spec in self._job_specs] - byte_job_specs_bunches: List[List[bytes]] = [] - bunch_sizes = [] - bunch: List[bytes] = [] - bunch_n_bytes = 0 - bunch_n_jobs = 0 - for spec in byte_job_specs: - n_bytes = len(spec) - assert n_bytes < max_bunch_bytesize, ( - 'every job spec must be less than max_bunch_bytesize,' - f' { max_bunch_bytesize }B, but {spec.decode()} is larger') - if bunch_n_bytes + n_bytes < max_bunch_bytesize and len(bunch) < max_bunch_size: - bunch.append(spec) - bunch_n_bytes += n_bytes - bunch_n_jobs += 1 - else: - byte_job_specs_bunches.append(bunch) - bunch_sizes.append(bunch_n_jobs) - bunch = [spec] - bunch_n_bytes = n_bytes - bunch_n_jobs = 1 - if bunch: - byte_job_specs_bunches.append(bunch) - bunch_sizes.append(bunch_n_jobs) - if progress is not None: - start_job_id = await self._submit_bunches(byte_job_specs_bunches, - bunch_sizes, - progress, - disable_progress_bar) + if progress: + start_job_id = await self._submit(max_bunch_bytesize, max_bunch_size, disable_progress_bar, None, progress) else: - n_bunches = len(byte_job_specs_bunches) - with BatchProgressBar(disable=disable_progress_bar or n_bunches < 100) as progress2: - start_job_id = await self._submit_bunches(byte_job_specs_bunches, - bunch_sizes, - progress2, - disable_progress_bar) + with BatchProgressBar(disable=disable_progress_bar) as progress2: + start_job_id = await self._submit(max_bunch_bytesize, max_bunch_size, disable_progress_bar, 100, progress2) + assert self._batch is not None for j in self._jobs: + assert start_job_id is not None j._job = j._job._submit(self._batch, start_job_id) self._job_specs = [] From 7530ad0af6dd433f7edd25e76c9bbee4a68f5053 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 18 Aug 2023 13:01:22 -0400 Subject: [PATCH 116/180] [hailctl] Dont change the current python environment in test fixture (#13457) Sorry missed this in the initial PR. `os.environ` is global to the whole python session so setting it directly could inadvertently affect the environment for unrelated tests. There seems to be safe ways to do this using `monkeypatch` and whatever `CliRunner` is doing, but I decided just not to set it. --- hail/python/hailtop/config/user_config.py | 4 +-- .../test/hailtop/hailctl/config/conftest.py | 32 ------------------- .../test/hailtop/hailctl/config/test_cli.py | 19 +++++++++-- 3 files changed, 18 insertions(+), 37 deletions(-) diff --git a/hail/python/hailtop/config/user_config.py b/hail/python/hailtop/config/user_config.py index fcd8c072faa..208d02674cf 100644 --- a/hail/python/hailtop/config/user_config.py +++ b/hail/python/hailtop/config/user_config.py @@ -17,8 +17,8 @@ def xdg_config_home() -> Path: return Path(value) -def get_user_config_path() -> Path: - return Path(xdg_config_home(), 'hail', 'config.ini') +def get_user_config_path(*, _config_dir: Optional[str] = None) -> Path: + return Path(_config_dir or xdg_config_home(), 'hail', 'config.ini') def get_user_config() -> configparser.ConfigParser: diff --git a/hail/python/test/hailtop/hailctl/config/conftest.py b/hail/python/test/hailtop/hailctl/config/conftest.py index 8818cfa3e0c..95ca40e0f4d 100644 --- a/hail/python/test/hailtop/hailctl/config/conftest.py +++ b/hail/python/test/hailtop/hailctl/config/conftest.py @@ -1,4 +1,3 @@ -import os import pytest import tempfile @@ -14,34 +13,3 @@ def config_dir(): @pytest.fixture def runner(config_dir): yield CliRunner(mix_stderr=False, env={'XDG_CONFIG_HOME': config_dir}) - - -@pytest.fixture -def bc_runner(config_dir): - from hailtop.config import get_user_config, get_user_config_path # pylint: disable=import-outside-toplevel - - # necessary for backwards compatibility test - os.environ['XDG_CONFIG_HOME'] = config_dir - - config = get_user_config() - config_file = get_user_config_path() - - items = [ - ('global', 'email', 'johndoe@gmail.com'), - ('batch', 'foo', '5') - ] - - for section, key, value in items: - if section not in config: - config[section] = {} - config[section][key] = value - - try: - f = open(config_file, 'w', encoding='utf-8') - except FileNotFoundError: - os.makedirs(config_file.parent, exist_ok=True) - f = open(config_file, 'w', encoding='utf-8') - with f: - config.write(f) - - yield CliRunner(mix_stderr=False, env={'XDG_CONFIG_HOME': config_dir}) diff --git a/hail/python/test/hailtop/hailctl/config/test_cli.py b/hail/python/test/hailtop/hailctl/config/test_cli.py index 3a595aeb81c..8cb5af3a8da 100644 --- a/hail/python/test/hailtop/hailctl/config/test_cli.py +++ b/hail/python/test/hailtop/hailctl/config/test_cli.py @@ -1,8 +1,10 @@ +import os import pytest from typer.testing import CliRunner from hailtop.config.variables import ConfigVariable +from hailtop.config.user_config import get_user_config_path from hailtop.hailctl.config import cli, config_variables @@ -60,12 +62,23 @@ def test_config_set_get_list_unset(name: str, value: str, runner: CliRunner): # backwards compatibility -def test_config_get_unknown_names(bc_runner: CliRunner): - res = bc_runner.invoke(cli.app, ['get', 'email'], catch_exceptions=False) +def test_config_get_unknown_names(runner: CliRunner, config_dir: str): + config_path = get_user_config_path(_config_dir=config_dir) + os.makedirs(os.path.dirname(config_path)) + with open(config_path, 'w', encoding='utf-8') as config: + config.write(f''' +[global] +email = johndoe@gmail.com + +[batch] +foo = 5 +''') + + res = runner.invoke(cli.app, ['get', 'email'], catch_exceptions=False) assert res.exit_code == 0 assert res.stdout.strip() == 'johndoe@gmail.com' - res = bc_runner.invoke(cli.app, ['get', 'batch/foo'], catch_exceptions=False) + res = runner.invoke(cli.app, ['get', 'batch/foo'], catch_exceptions=False) assert res.exit_code == 0 assert res.stdout.strip() == '5' From 7b7c9d66779e381276a1a7f2355ec9b0021faab9 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 18 Aug 2023 14:39:38 -0400 Subject: [PATCH 117/180] [dev-docs] Instructions for resetting a dev database (#13456) This also fixes the currently broken `delete_*_tables` steps. In the past, all dev and test databases shared the same MySQL Server (with production), so instead of each service getting its own dedicated database, there was one database per dev/test namespace with all the tables for all the services. This made it difficult to reset the database state of a particular service -- you needed to explicitly delete only the tables for that particular service. Nowadays, dev and test databases live on their own MySQL Servers, so each service gets its own database (like in production). This makes it a lot easier to reset a service's database, we just drop the MySQL database for that service. This PR makes that change, deletes all the now unused `delete-*-tables.sql` files, and adds a dev doc explaining how to reset a dev database. The reason these steps were broken is that the sql configs in dev/test namespaces use K8s DNS for the `host`, which does not work out of the box in batch jobs because they are not in the K8s network. There's code in `database.py` that uses the K8s API to resolve the database host to an IP address that the batch jobs can access. This is why I wrote a python script instead of just using `mysql`. I tested these with the following dev deploy, which scrapped everything and I was able to log in after it was done! ``` hailctl dev deploy -b daniel-goldstein/hail:dev-ns-delete-db -s delete_auth_tables,delete_batch_tables,deploy_batch,add_developers ``` cc: @sjparsa, @iris-garden given your recent dev namespace woes --- auth/sql/delete-auth-tables.sql | 9 -- batch/sql/delete-batch-tables.sql | 83 -------------- build.yaml | 114 ++++++++++++-------- check-sql.sh | 2 +- ci/delete_dev_database.py | 17 +++ ci/sql/delete-ci-tables.sql | 11 -- dev-docs/services-development-faq.md | 31 ++++++ monitoring/sql/delete-monitoring-tables.sql | 4 - 8 files changed, 116 insertions(+), 155 deletions(-) delete mode 100644 auth/sql/delete-auth-tables.sql delete mode 100644 batch/sql/delete-batch-tables.sql create mode 100644 ci/delete_dev_database.py delete mode 100644 ci/sql/delete-ci-tables.sql create mode 100644 dev-docs/services-development-faq.md delete mode 100644 monitoring/sql/delete-monitoring-tables.sql diff --git a/auth/sql/delete-auth-tables.sql b/auth/sql/delete-auth-tables.sql deleted file mode 100644 index d7ad883b26d..00000000000 --- a/auth/sql/delete-auth-tables.sql +++ /dev/null @@ -1,9 +0,0 @@ -DROP EVENT IF EXISTS `purge_sessions`; -DROP EVENT IF EXISTS `purge_copy_paste_tokens`; - -DROP TABLE IF EXISTS `copy_paste_tokens`; -DROP TABLE IF EXISTS `sessions`; -DROP TABLE IF EXISTS `users`; -DROP TABLE IF EXISTS `auth_migration_version`; -DROP TABLE IF EXISTS `auth_migrations`; -DROP TABLE IF EXISTS `roles`; diff --git a/batch/sql/delete-batch-tables.sql b/batch/sql/delete-batch-tables.sql deleted file mode 100644 index c59e928b6e8..00000000000 --- a/batch/sql/delete-batch-tables.sql +++ /dev/null @@ -1,83 +0,0 @@ -DROP PROCEDURE IF EXISTS recompute_incremental; -DROP PROCEDURE IF EXISTS cancel_batch; -DROP PROCEDURE IF EXISTS activate_instance; -DROP PROCEDURE IF EXISTS deactivate_instance; -DROP PROCEDURE IF EXISTS mark_instance_deleted; -DROP PROCEDURE IF EXISTS close_batch; -DROP PROCEDURE IF EXISTS commit_batch_update; -DROP PROCEDURE IF EXISTS schedule_job; -DROP PROCEDURE IF EXISTS unschedule_job; -DROP PROCEDURE IF EXISTS mark_job_creating; -DROP PROCEDURE IF EXISTS mark_job_started; -DROP PROCEDURE IF EXISTS mark_job_complete; -DROP PROCEDURE IF EXISTS add_attempt; - -DROP TRIGGER IF EXISTS batches_before_insert; -DROP TRIGGER IF EXISTS batches_after_insert; -DROP TRIGGER IF EXISTS batches_before_update; -DROP TRIGGER IF EXISTS batches_after_update; -DROP TRIGGER IF EXISTS instances_before_update; -DROP TRIGGER IF EXISTS attempts_before_update; -DROP TRIGGER IF EXISTS attempts_after_update; -DROP TRIGGER IF EXISTS jobs_after_update; -DROP TRIGGER IF EXISTS attempt_resources_after_insert; -DROP TRIGGER IF EXISTS attempt_resources_before_insert; # deprecated -DROP TRIGGER IF EXISTS aggregated_bp_user_resources_v2_before_insert; -DROP TRIGGER IF EXISTS aggregated_bp_user_resources_by_date_v2_before_insert; -DROP TRIGGER IF EXISTS aggregated_batch_resources_v2_before_insert; -DROP TRIGGER IF EXISTS aggregated_job_resources_v2_before_insert; -DROP TRIGGER IF EXISTS aggregated_bp_user_resources_v2_after_update; -DROP TRIGGER IF EXISTS aggregated_bp_user_resources_by_date_v2_after_update; -DROP TRIGGER IF EXISTS aggregated_batch_resources_v2_after_update; -DROP TRIGGER IF EXISTS aggregated_job_resources_v2_after_update; - -DROP TABLE IF EXISTS `aggregated_job_resources_by_date`; -DROP TABLE IF EXISTS `aggregated_batch_resources_by_date`; -DROP TABLE IF EXISTS `aggregated_billing_project_user_resources_by_date`; -DROP TABLE IF EXISTS `batch_updates_inst_coll_staging`; -DROP TABLE IF EXISTS `batch_inst_coll_cancellable_resources_staging`; - -DROP TABLE IF EXISTS `aggregated_billing_project_resources`; -DROP TABLE IF EXISTS `aggregated_billing_project_user_resources_v2`; -DROP TABLE IF EXISTS `aggregated_billing_project_user_resources_v3`; -DROP TABLE IF EXISTS `aggregated_billing_project_user_resources_by_date_v2`; -DROP TABLE IF EXISTS `aggregated_billing_project_user_resources_by_date_v3`; -DROP TABLE IF EXISTS `aggregated_batch_resources`; -DROP TABLE IF EXISTS `aggregated_batch_resources_v2`; -DROP TABLE IF EXISTS `aggregated_batch_resources_v3`; -DROP TABLE IF EXISTS `aggregated_job_resources`; -DROP TABLE IF EXISTS `aggregated_job_resources_v2`; -DROP TABLE IF EXISTS `aggregated_job_resources_v3`; -DROP TABLE IF EXISTS `attempt_resources`; -DROP TABLE IF EXISTS `batch_cancellable_resources`; # deprecated -DROP TABLE IF EXISTS `batch_inst_coll_cancellable_resources`; -DROP TABLE IF EXISTS `globals`; -DROP TABLE IF EXISTS `attempts`; -DROP TABLE IF EXISTS `batch_attributes`; -DROP TABLE IF EXISTS `job_attributes`; -DROP TABLE IF EXISTS `job_parents`; -DROP TABLE IF EXISTS `batch_bunches`; -DROP TABLE IF EXISTS `ready_cores`; # deprecated -DROP TABLE IF EXISTS `gevents_mark`; # deprecated -DROP TABLE IF EXISTS `events_mark`; -DROP TABLE IF EXISTS `jobs`; -DROP TABLE IF EXISTS `batches_cancelled`; -DROP TABLE IF EXISTS `batches_staging`; # deprecated -DROP TABLE IF EXISTS `batches_inst_coll_staging`; -DROP TABLE IF EXISTS `batch_updates`; -DROP TABLE IF EXISTS `batches_n_jobs_in_complete_states`; -DROP TABLE IF EXISTS `batches`; -DROP TABLE IF EXISTS `user_resources`; # deprecated -DROP TABLE IF EXISTS `user_inst_coll_resources`; -DROP TABLE IF EXISTS `instances_free_cores_mcpu`; -DROP TABLE IF EXISTS `instances`; -DROP TABLE IF EXISTS `billing_project_users`; -DROP TABLE IF EXISTS `billing_projects`; -DROP TABLE IF EXISTS `batch_migration_version`; -DROP TABLE IF EXISTS `batch_migrations`; -DROP TABLE IF EXISTS `pools`; -DROP TABLE IF EXISTS `inst_colls`; -DROP TABLE IF EXISTS `latest_product_versions`; -DROP TABLE IF EXISTS `resources`; -DROP TABLE IF EXISTS `regions`; -DROP TABLE IF EXISTS `feature_flags`; diff --git a/build.yaml b/build.yaml index 3398e8a597b..24dcbdcb206 100644 --- a/build.yaml +++ b/build.yaml @@ -334,27 +334,59 @@ steps: to: /io/repo/admin-pod dependsOn: - hail_ubuntu_image + - kind: buildImage2 + name: auth_image + dockerFile: /io/repo/auth/Dockerfile + contextPath: /io/repo + publishAs: auth + resources: + storage: 10Gi + cpu: "2" + memory: standard + inputs: + - from: /repo/auth + to: /io/repo/auth + - from: /repo/hail/python/setup-hailtop.py + to: /io/repo/hail/python/setup-hailtop.py + - from: /repo/hail/python/MANIFEST.in + to: /io/repo/hail/python/MANIFEST.in + - from: /repo/hail/python/hailtop + to: /io/repo/hail/python/hailtop + - from: /hail_version + to: /io/repo/hail/python/hailtop/hail_version + - from: /repo/gear + to: /io/repo/gear + - from: /repo/web_common + to: /io/repo/web_common + dependsOn: + - hail_ubuntu_image + - merge_code - kind: runImage name: delete_auth_tables image: - valueFrom: admin_pod_image.image + valueFrom: auth_image.image script: | set -ex - mysql --defaults-extra-file=/sql-config/sql-config.cnf < /io/sql/delete-auth-tables.sql + cd /io + python3 delete_dev_database.py {{ default_ns.name }} auth inputs: - - from: /repo/auth/sql - to: /io/sql + - from: /repo/ci/delete_dev_database.py + to: /io/delete_dev_database.py secrets: - name: database-server-config namespace: valueFrom: default_ns.name mountPath: /sql-config + serviceAccount: + name: admin + namespace: + valueFrom: default_ns.name runIfRequested: true scopes: - dev dependsOn: - default_ns - - admin_pod_image + - auth_image - merge_code - create_test_database_server_config - kind: createDatabase2 @@ -490,33 +522,6 @@ steps: dependsOn: - default_ns - ci_utils_image - - kind: buildImage2 - name: auth_image - dockerFile: /io/repo/auth/Dockerfile - contextPath: /io/repo - publishAs: auth - resources: - storage: 10Gi - cpu: "2" - memory: standard - inputs: - - from: /repo/auth - to: /io/repo/auth - - from: /repo/hail/python/setup-hailtop.py - to: /io/repo/hail/python/setup-hailtop.py - - from: /repo/hail/python/MANIFEST.in - to: /io/repo/hail/python/MANIFEST.in - - from: /repo/hail/python/hailtop - to: /io/repo/hail/python/hailtop - - from: /hail_version - to: /io/repo/hail/python/hailtop/hail_version - - from: /repo/gear - to: /io/repo/gear - - from: /repo/web_common - to: /io/repo/web_common - dependsOn: - - hail_ubuntu_image - - merge_code - kind: deploy name: deploy_auth_driver_service_account namespace: @@ -1631,24 +1636,29 @@ steps: - kind: runImage name: delete_monitoring_tables image: - valueFrom: admin_pod_image.image + valueFrom: monitoring_image.image script: | set -ex - mysql --defaults-extra-file=/sql-config/sql-config.cnf < /io/sql/delete-monitoring-tables.sql + cd /io + python3 delete_dev_database.py {{ default_ns.name }} monitoring inputs: - - from: /repo/monitoring/sql - to: /io/sql + - from: /repo/ci/delete_dev_database.py + to: /io/delete_dev_database.py secrets: - name: database-server-config namespace: valueFrom: default_ns.name mountPath: /sql-config + serviceAccount: + name: admin + namespace: + valueFrom: default_ns.name runIfRequested: true scopes: - dev dependsOn: - default_ns - - admin_pod_image + - monitoring_image - merge_code - create_test_database_server_config - kind: createDatabase2 @@ -1842,47 +1852,57 @@ steps: - kind: runImage name: delete_batch_tables image: - valueFrom: admin_pod_image.image + valueFrom: batch_image.image script: | set -ex - mysql --defaults-extra-file=/sql-config/sql-config.cnf < /io/sql/delete-batch-tables.sql + cd /io + python3 delete_dev_database.py {{ default_ns.name }} batch inputs: - - from: /repo/batch/sql - to: /io/sql + - from: /repo/ci/delete_dev_database.py + to: /io/delete_dev_database.py secrets: - name: database-server-config namespace: valueFrom: default_ns.name mountPath: /sql-config + serviceAccount: + name: admin + namespace: + valueFrom: default_ns.name runIfRequested: true scopes: - dev dependsOn: - default_ns - - admin_pod_image + - batch_image - merge_code - create_test_database_server_config - kind: runImage name: delete_ci_tables image: - valueFrom: admin_pod_image.image + valueFrom: ci_image.image script: | set -ex - mysql --defaults-extra-file=/sql-config/sql-config.cnf < /io/sql/delete-ci-tables.sql + cd /io + python3 delete_dev_database.py {{ default_ns.name }} ci inputs: - - from: /repo/ci/sql - to: /io/sql + - from: /repo/ci/delete_dev_database.py + to: /io/delete_dev_database.py secrets: - name: database-server-config namespace: valueFrom: default_ns.name mountPath: /sql-config + serviceAccount: + name: admin + namespace: + valueFrom: default_ns.name runIfRequested: true scopes: - dev dependsOn: - default_ns - - admin_pod_image + - ci_image - merge_code - create_test_database_server_config - kind: createDatabase2 diff --git a/check-sql.sh b/check-sql.sh index c21fb4f98e6..8779bce56a9 100755 --- a/check-sql.sh +++ b/check-sql.sh @@ -14,7 +14,7 @@ if [ ! -d sql ]; then fi git diff --name-status $target_treeish sql \ - | grep -Ev $'^A|^M\t[^/]+/sql/(estimated-current.sql|delete-[^ ]+-tables.sql)' \ + | grep -Ev $'^A|^M|^D\t[^/]+/sql/(estimated-current.sql|delete-[^ ]+-tables.sql)' \ > $modified_sql_file_list if [ "$(cat $modified_sql_file_list | wc -l)" -ne 0 ] diff --git a/ci/delete_dev_database.py b/ci/delete_dev_database.py new file mode 100644 index 00000000000..1b15e73230a --- /dev/null +++ b/ci/delete_dev_database.py @@ -0,0 +1,17 @@ +import asyncio +import sys + +from gear import Database + +namespace = sys.argv[1] +database = sys.argv[2] +assert namespace != 'default' + + +async def main(): + db = Database() + await db.async_init() + await db.just_execute(f'DROP DATABASE `{namespace}-{database}`;') + + +asyncio.run(main()) diff --git a/ci/sql/delete-ci-tables.sql b/ci/sql/delete-ci-tables.sql deleted file mode 100644 index c3276d55356..00000000000 --- a/ci/sql/delete-ci-tables.sql +++ /dev/null @@ -1,11 +0,0 @@ -DROP TABLE IF EXISTS `hello2`; -DROP TABLE IF EXISTS `hello_migration_version`; -DROP TABLE IF EXISTS `hello_migrations`; -DROP TABLE IF EXISTS `ci_migration_version`; -DROP TABLE IF EXISTS `ci_migrations`; -DROP TABLE IF EXISTS `authorized_shas`; -DROP TABLE IF EXISTS `invalidated_batches`; -DROP TABLE IF EXISTS `globals`; -DROP TABLE IF EXISTS `active_namespaces`; -DROP TABLE IF EXISTS `deployed_services`; -DROP TABLE IF EXISTS `alerted_failed_shas`; diff --git a/dev-docs/services-development-faq.md b/dev-docs/services-development-faq.md new file mode 100644 index 00000000000..e18a73013e2 --- /dev/null +++ b/dev-docs/services-development-faq.md @@ -0,0 +1,31 @@ +# FAQ when developing Hail Batch + +#### I messed up the Batch database in my dev namespace. How do I start fresh? + +If you only want to delete the Batch database and leave the other databases alone, +you can submit a dev deploy using the `delete_batch_tables` job. The following +will create a dev deploy that removes your current Batch database and redeploys +Batch with a fresh one: + +```bash +hailctl dev deploy -b /hail: -s delete_batch_tables,deploy_batch +``` + +If you want to start totally clean, another option is to delete your dev namespace's +database completely by deleting the underlying Kubernetes resources. +The database is a Kubernetes `StatefulSet`, with the data stored in a +persistent disk owned by a `PersistentVolumeClaim`. Deleting the `StatefulSet` will +delete the MySQL pod, but not the underlying claim/data. +So to get a totally clean slate, you must delete both resources: + +```bash +kubectl -n delete statefulset db +# When that's done... +kubectl -n delete pvc mysql-persistent-storage-db-0 +``` + +The next dev deploy will set up a new database: + +```bash +hailctl dev deploy -b /hail: -s deploy_batch,add_developers +``` diff --git a/monitoring/sql/delete-monitoring-tables.sql b/monitoring/sql/delete-monitoring-tables.sql deleted file mode 100644 index a4d39ac05dc..00000000000 --- a/monitoring/sql/delete-monitoring-tables.sql +++ /dev/null @@ -1,4 +0,0 @@ -DROP TABLE IF EXISTS `monitoring_billing_mark`; -DROP TABLE IF EXISTS `monitoring_billing_data`; -DROP TABLE IF EXISTS `monitoring_migration_version`; -DROP TABLE IF EXISTS `monitoring_migrations`; From c032637b2f35ea50c076fb0ffa4a308f16dc3f04 Mon Sep 17 00:00:00 2001 From: Patrick Schultz Date: Fri, 18 Aug 2023 16:15:58 -0400 Subject: [PATCH 118/180] =?UTF-8?q?[compiler]=20restore=20support=20for=20?= =?UTF-8?q?dropRows=E2=80=A6=20(#13460)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … on TableRead when whole-stage codegen is turned off. --- .../main/scala/is/hail/expr/ir/TableIR.scala | 19 +++++++++++++++++-- .../hail/expr/ir/lowering/LowerTableIR.scala | 12 +----------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/hail/src/main/scala/is/hail/expr/ir/TableIR.scala b/hail/src/main/scala/is/hail/expr/ir/TableIR.scala index ffff0b15c4a..837142e5a70 100644 --- a/hail/src/main/scala/is/hail/expr/ir/TableIR.scala +++ b/hail/src/main/scala/is/hail/expr/ir/TableIR.scala @@ -481,9 +481,23 @@ trait TableReaderWithExtraUID extends TableReader { abstract class TableReader { def pathsUsed: Seq[String] + final def lower(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableStage = { + if (dropRows) { + val globals = lowerGlobals(ctx, requestedType.globalType) + + TableStage( + globals, + RVDPartitioner.empty(ctx, requestedType.keyType), + TableStageDependency.none, + MakeStream(FastIndexedSeq(), TStream(TStruct.empty)), + (_: Ref) => MakeStream(FastIndexedSeq(), TStream(requestedType.rowType))) + } else { + lower(ctx, requestedType) + } + } + def toExecuteIntermediate(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableExecuteIntermediate = { - assert(!dropRows) - TableExecuteIntermediate(lower(ctx, requestedType)) + TableExecuteIntermediate(lower(ctx, requestedType, dropRows)) } def partitionCounts: Option[IndexedSeq[Long]] @@ -1608,6 +1622,7 @@ case class TableFromBlockMatrixNativeReader( VirtualTypeWithReq(PCanonicalStruct.empty(required = true)) override def toExecuteIntermediate(ctx: ExecuteContext, requestedType: TableType, dropRows: Boolean): TableExecuteIntermediate = { + assert(!dropRows) val rowsRDD = new BlockMatrixReadRowBlockedRDD( ctx.fsBc, params.path, partitionRanges, requestedType.rowType, metadata, maybeMaximumCacheMemoryInBytes = params.maximumCacheMemoryInBytes) diff --git a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala index 8cc95c205e8..87909ba48c9 100644 --- a/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala +++ b/hail/src/main/scala/is/hail/expr/ir/lowering/LowerTableIR.scala @@ -826,17 +826,7 @@ object LowerTableIR { val lowered: TableStage = tir match { case TableRead(typ, dropRows, reader) => - if (dropRows) { - val globals = reader.lowerGlobals(ctx, typ.globalType) - - TableStage( - globals, - RVDPartitioner.empty(ctx, typ.keyType), - TableStageDependency.none, - MakeStream(FastIndexedSeq(), TStream(TStruct.empty)), - (_: Ref) => MakeStream(FastIndexedSeq(), TStream(typ.rowType))) - } else - reader.lower(ctx, typ) + reader.lower(ctx, typ, dropRows) case TableParallelize(rowsAndGlobal, nPartitions) => val nPartitionsAdj = nPartitions.getOrElse(ctx.backend.defaultParallelism) From 83a6c05a6f12108e4718846e176cc3a28948cc13 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 18 Aug 2023 17:42:16 -0400 Subject: [PATCH 119/180] [hailctl] clarify suggested use of -- and allow it in hailctl batch submit (#13447) CHANGELOG: Resolves #13446. In all three submit commands (batch, dataproc, and hdinsight), Hail now allows and encourages the use of -- to separate arguments meant for the user script from those meant for hailctl. In hailctl batch submit, option-like arguments, for example "--foo", are now supported before "--" if and only if they do not conflict with a hailctl option. --- hail/python/hailtop/hailctl/batch/cli.py | 16 ++++++++++++---- hail/python/hailtop/hailctl/dataproc/cli.py | 16 +++++++++++----- hail/python/hailtop/hailctl/hdinsight/cli.py | 9 ++++++++- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/hail/python/hailtop/hailctl/batch/cli.py b/hail/python/hailtop/hailctl/batch/cli.py index ebc1e31fd26..841cd63e94f 100644 --- a/hail/python/hailtop/hailctl/batch/cli.py +++ b/hail/python/hailtop/hailctl/batch/cli.py @@ -149,10 +149,11 @@ def job(batch_id: int, job_id: int, output: StructuredFormatOption = StructuredF print(f"Job with ID {job_id} on batch {batch_id} not found") -@app.command() +@app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": True}) def submit( + ctx: typer.Context, script: str, - arguments: Ann[Optional[List[str]], Arg()] = None, + arguments: Ann[Optional[List[str]], Arg(help='You should use -- if you want to pass option-like arguments through.')] = None, files: Ann[ Optional[List[str]], Opt(help='Files or directories to add to the working directory of the job.') ] = None, @@ -160,5 +161,12 @@ def submit( image_name: Ann[Optional[str], Opt(help='Name of Docker image for the job (default: hailgenetics/hail)')] = None, output: StructuredFormatPlusTextOption = StructuredFormatPlusText.TEXT, ): - '''Submit a batch with a single job that runs SCRIPT with the arguments ARGUMENTS.''' - asyncio.run(_submit.submit(name, image_name, files or [], output, script, arguments or [])) + '''Submit a batch with a single job that runs SCRIPT with the arguments ARGUMENTS. + + If you wish to pass option-like arguments you should use "--". For example: + + + + $ hailctl batch submit --image-name docker.io/image my_script.py -- some-argument --animal dog + ''' + asyncio.run(_submit.submit(name, image_name, files or [], output, script, [*(arguments or []), *ctx.args])) diff --git a/hail/python/hailtop/hailctl/dataproc/cli.py b/hail/python/hailtop/hailctl/dataproc/cli.py index f4192886c7f..3ee648fa216 100644 --- a/hail/python/hailtop/hailctl/dataproc/cli.py +++ b/hail/python/hailtop/hailctl/dataproc/cli.py @@ -317,13 +317,19 @@ def submit( ] = None, dry_run: DryRunOption = False, region: Ann[Optional[str], Opt(help='Compute region for the cluster.')] = None, + arguments: Ann[Optional[List[str]], Arg(help='You should use -- if you want to pass option-like arguments through.')] = None, ): + '''Submit the Python script at path SCRIPT to a running Dataproc cluster with name NAME. + + You may pass arguments to the script being submitted by listing them after the script; however, + if you wish to pass option-like arguments you should use "--". For example: + + + + $ hailctl dataproc submit name --image-name docker.io/image my_script.py -- some-argument --animal dog + ''' - Submit the Python script at path SCRIPT to a running Dataproc cluster with - name NAME. To pass arguments to the script being submitted, just list them - after the name of the script. - ''' - dataproc_submit(name, script, files, pyfiles, properties, gcloud_configuration, dry_run, region, ctx.args) + dataproc_submit(name, script, files, pyfiles, properties, gcloud_configuration, dry_run, region, [*(arguments or []), *ctx.args]) @app.command() diff --git a/hail/python/hailtop/hailctl/hdinsight/cli.py b/hail/python/hailtop/hailctl/hdinsight/cli.py index 2846c8b35d9..76fe14ab95c 100644 --- a/hail/python/hailtop/hailctl/hdinsight/cli.py +++ b/hail/python/hailtop/hailctl/hdinsight/cli.py @@ -153,11 +153,18 @@ def submit( storage_account: Ann[str, Arg(help="Storage account in which the cluster's container exists.")], http_password: Ann[str, Arg(help='Web password for the cluster')], script: Ann[str, Arg(help='Path to script.')], + arguments: Ann[Optional[List[str]], Arg(help='You should use -- if you want to pass option-like arguments through.')] = None, ): ''' Submit a job to an HDInsight cluster configured for Hail. + + If you wish to pass option-like arguments you should use "--". For example: + + + + $ hailctl hdinsight submit name account password script.py --image-name docker.io/image my_script.py -- some-argument --animal dog ''' - hdinsight_submit(name, storage_account, http_password, script, ctx.args) + hdinsight_submit(name, storage_account, http_password, script, [*(arguments or []), *ctx.args]) @app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": True}) From 541e8201b867bd77f20fbde7e15b5993b4c38687 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 18 Aug 2023 18:50:52 -0400 Subject: [PATCH 120/180] [query] fix ./gradlew test (#13459) TestNG (appears to) allocates every class in the classpath matching the package glob. I assume this is to check if any of these are `instanceof` `TestNGSuite`. The Azure SDK depends on `rector-netty-core` which includes some classes which reference interfaces *not included in its required dependencies*. These classes are meant to be used only when those optional dependencies are present. They should not be willy-nilly allocated, but, of course, we told TestNG to go willy-nilly allocating everything. --- hail/testng.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/hail/testng.xml b/hail/testng.xml index eee0db8678d..f6ca19bb985 100644 --- a/hail/testng.xml +++ b/hail/testng.xml @@ -2,6 +2,7 @@ + From 8f096835e1561ab42b60418f37abd7f871b36611 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 18 Aug 2023 20:06:21 -0400 Subject: [PATCH 121/180] [k8s] Scale down dev namespaces every night (#13462) --- build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.yaml b/build.yaml index 24dcbdcb206..71016672804 100644 --- a/build.yaml +++ b/build.yaml @@ -3722,7 +3722,7 @@ steps: name: dev-namespace-scaledown-{{ user["username"] }} namespace: {{ user["username"] }} spec: - schedule: "0 0 * * 1,2,3,4,5" # Weekdays at midnight UTC + schedule: "0 0 * * *" # Every day at midnight UTC concurrencyPolicy: Forbid successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 1 From 86563a74930f0bed4bc88b47d598da71113d9770 Mon Sep 17 00:00:00 2001 From: Dan King Date: Mon, 21 Aug 2023 11:28:11 -0400 Subject: [PATCH 122/180] [query] add more examples of using hl.import_vcf (#13464) I also improved the docs a bit. This was just a long-standing todo item of mine. --- hail/python/hail/docs/data/sample.vcf.gz | Bin 0 -> 192983 bytes hail/python/hail/docs/data/samplepart1.vcf | 160 +++++++++++++++++++ hail/python/hail/docs/data/samplepart2.vcf | 170 ++++++++++++++++++++ hail/python/hail/docs/data/samplepart3.vcf | 172 +++++++++++++++++++++ hail/python/hail/methods/impex.py | 38 +++-- 5 files changed, 531 insertions(+), 9 deletions(-) create mode 100644 hail/python/hail/docs/data/sample.vcf.gz create mode 100644 hail/python/hail/docs/data/samplepart1.vcf create mode 100644 hail/python/hail/docs/data/samplepart2.vcf create mode 100644 hail/python/hail/docs/data/samplepart3.vcf diff --git a/hail/python/hail/docs/data/sample.vcf.gz b/hail/python/hail/docs/data/sample.vcf.gz new file mode 100644 index 0000000000000000000000000000000000000000..2d28fe2bb1e544e599e2497daf4d23bb9be6ba18 GIT binary patch literal 192983 zcmV(=K-s?^iwFb&00000{{{d;LjnLiIqiK}a~wyK<}>D3z-AtH#*CG7b+9k1zcEmw)-@ z^4;;9tLyJBZXf*d(bMnU-u%2Oc!dnUoto2!r4ua6IYe{uQld$m{a z2OQ{_b!3@@BsKo0;GAcYo90UTFpUQT@-K@$Sj5zI^^Ayco)G(_P<7cP3DI@9yN` z_kIF#+BX+o{OtMDKhSH>pFDf`>a#yS`SYu<9)9-x&o4iF^+fiwD*O5AyNgB$zIuCk zbN>Cs_2tF;+w&h_pMJc7O?rEE{`JSpcW-E`zCV5oJM{bG`R(<^<$DmL=QqdO^Q&*p zzXoZ-*Szq!8p?)>(6Lv8;4;`+^x=YKk0zK55; zJ%93FFpSHuuP;A-H|^o!BkADbmXJQ4zrOkivjfRfCDM)r)bZl=+w+H?zhX(f6XA4o z@tufkpvXvK*Y00`eD~q{^7e#N<`uMe@gBM*DR=(E+e_#Z35^~7aCHsS{&2j;Lk}s- z19*1v@#Y5Tdj8$zUv58MAJ4zLdUJfYD-!lcK4>m(sJ-&%cnRUayghyYnwDK77D2@nLcPAIIyfb3B5Y#l}ZpUfq0k@%}$we*A8G-Twp5i>qs1 z_di{}dwum6m*Mha5aZF+@tbe9r#QR-ya#VwzP>!d;=tO#eokDS=p^K@_q4S#?}k-{Ni}A zMXoRZ07t>6KNre=TsRlL1rF{U3~;i2{)flgv-M_HmGQ z-yg4UKHl(W-(0-AfhB&AOo`*8Vd17;6sFU0J$iRZ!tTyO?CI%3Y!Ezek=b8kmoU7q zFK*fe`*(Qs;;$i3|HwnZKF|M)gFeZ0AWrQ{=xgbJUG51;;8|@Xc$GR*j7P_f5(4=4-&j=U*K0TQ_enKQzem;=?;SO<&@k*q$@Y^#*B zN5B8-4_}WIv)Een;g%zu}r)erx_4dMUqi z`EB@fWBIo$zoEzSo1eox%J1;!hy0QE!#}xIpZGVo9=P>bdN;N_H_q^H%fB7}u1y;6 z`FCm31b!v(R|9_@`14pkw<_@O^4x08zxi_>stx=+@b`l}=l4Pxs*U_TX+K*2&EJpw zy`=be8J|;@f6L$Hdrm94^tvh>o_UufD6p};5%NZ&p&wl@>FCXZ=dUDU*fB5J@%J*3j09TUxaJhb< z?oV&S57gdzd;j6{2S%y;%{>x6)Ygal51+!nd@}dzo#{bRZlCS_r!V0Xb^q~~4`TE| z-RE1ugXrQu`}+&P{(eE&55hj{`wgmna1T0+{{9$VK5)=JK|US>p{55K_!=hkz~_C` z_g_4IVC-Ip`;Y(qem&#h`$pUQaN<1B(W(1zQan&+&t4rKK0ZAD^6>1%;mgm@)bG^6 zsvZ6~L~~HPXm(n`%B$b$gUdVT57`}ZJ^&%iPVKa#&(y)_9sW231uq474>ri+b8ah! zoi_&%Ce&C^@U@+RKg&x2UkZm{@g=*(oJk{^*qK8W~1ocEIOd73=e(2Lr^(E$HpA1Sz<_Auzq zxB|bC)B*m3H$Vo4opHMJM(G=<5_WKu$#SKL6G35upLxFv5y)?-JrLsfVF2O9UF8G( z2On7-VO>I!u6X|Q=>R1T_&>fAUD{byCZusepkG`ABB^x|*T=#5`Qrp!ghV1%a4IGI z*n)WGmf>CeA3t=!bk=8X85;6139AYZC67F$a#_cyX@)kH8HPw7!r@R_&A=~##^b%) znUuIqn3StC(bi-lOg3fu7N>9Ll-9`1%zqI%Zm03Y=&ueu%J@7VLcr%?mot+K2&WYc zS(`#GhihX7O2YvfX-!QCd1nkTsC<$SkyZ_kXtOgm3Y~zZaj}^bERn*3xD^89hmi;z zfZt)~@QXR`B8(^&uG4`wY4&B|oI>_0s|F_}Z8|&#dwen$Epz_K&_4|U@Q%jm)>&zX zo0{eYz382DGB229w6O5L43GHAL|@iF!#DB8!W>Q$6_aL)Wau48k(qN0QN)?@X4r*X zn}v61)~WKNMYf``dV|tJ8y*jAD&)tqa5~0RHdUCeH;N9Ra+PTd{J|Y*cfkK~T>uR1 zEbn;ak+4fJ^Rh<)Kp>Y|onjrLl5GJv4c<&bGT?KNT_A7E+yZSGJb7940jdLFRJKeJ z@WPisqvYYuSXfUNCdyvA1muhV!-pWufht~&c2t5PGovW%QpZ#zH|%91StumSB!^-a zIixdmnQ0*+($l9f@P)FtS%_z{&LDBJNU4QwD(}E3l`4D&ZCO=?Xmd`bEx~T^xtWWC zxbrY(#XNvifaPEUL)UNs!s8;8JaRdZKRek3FtRc@50ropcFid=I`{AmLvOI0Q1FIQ z^2WljSx5vpdy9|&t}sRfpAUGri{Nuv6Z5(_ZLSek@Xw${ctGzY1hUQL!?FW4i)Txs zGzF#;$QgTxw6s7i`po!32$0;cctyrJ3&(>WRy~Qxu@2=nGVoNgw2(naHyJs671!J1 zAo00|&1SrS92*Xa2j++jHZhjKPRt;_5-++>_)a-#bEbnfvM|v&eidLM^eG5m**JIRfn}8<%+!E)zXSQ|JcQH($h-$|Tr#4Yx9Nk_u(ua7+L{5J5vGd1Y-_ z*enU<&%j-a;vHz`cGfU^0qxAd`-|@|j0a!z3q;ND>JE{Zp) zhvM(y^}w3~bSh}{~00%BjrB|Ravf{FQggZ$^5SYPNpmqV@HjmNCptKQxXQT+7L%TfG@h>@zze_FLvVR`j{>p+#c{2fmal}F>NLw z91sXx5Z|lm<_L6^0#yYV|hbME~Af7M>wiNM3$?POd zPzS4GnoAFmPr!kuGpew@Kz-3MR}$&TH0u0}pzr2|Ae3!4aL{)W|H+5d0nPS%Pn%_z zfnk)L)$*R7F6d0cwe8qtIkS2G&g9jURjbI=vX;Gu1SvEFMQjH@5Q`%wM-5J15M&CD za^K3zc0bGAqNnV`U4kky6>ay%yo?p}`uAHR1+~0rIjt{(-0b=LIoJW&!h&Dlgyiwi zdv*5c4DdhPp(pxjKzYCyh;pqvML(@p^wY{3)=wKd0=3TCy&kKlZGd}O1+~`LeaIW? z>9nYx_A{vKeTBL(h5~aP47LDW0M7_?fdaABPQ!8Z8`k}+VckCE?uv9Z_F(CE@bK#JcKcs5~Y37ryAec9KFJF+{(f{|H)C54q1jbsXl>9Csisd$FPAXjafNNce=SQ7k->^s3%Ckr>(^tS?4G6ed2{^|}8-h?x}c zXbETg2pWS?eXPTOSI}&gP6&48L=6a_Zhqy;u7fz5gbn_WD` zsRNI9JGaPgx>{_wP0ZGF0|n0%FbE;KFgrKwD`A--iwB z>2Qx^Yl*CC7TV2mc0}`xx8)Uti2#4-6|{Bp@!29(v@Y=xrFBM?w%9V4tnY$J#EuAL zrBmN~FR~x-N-Br3)mrRyeI99`zE5NnbS&iqxk`w8O(;k@>$pNvXwdFLg7ZaJ(-w}< zuD#TkJRbR?xZbpyZ4{~qOXPqRtu3A)@M8eeqNT4#@{}nxZZ|mFi(yS`a<9oOi3J?b z#=Br+WwWqm_-!3}`c zq~s(-t{#Qq5_uRH!#b(1R9xU4cH06BUaa>Bn{{0aK*v@bbAadt(CV@ja1O&B2Hs#- z8Dih$r<-!-ZI=}}--N>S22C}v_NmSaZY1m$V~SDP7*(CS$dq4DnPo)5R(bT5%k29E zd#Ipmu|^3wkex#sgtA<vdo~IV9DlQ{wWsM1VJ1qd;_;RCSBUb-h zkPpNTqJ?9aXXkgoj_XE;;{6x8XXJugM*rkNM=D@THaU1w6nMeDk*+nwSUwk5D%*FN z8so|4>RBLpI0U{vkvCmx)y|Foq=s8nVy#U!1f-eIbRr z5%*Uh?Yu$vXyeeA`WXUgtC9^3kah|+%78Z2DM;F_YM-?cBpt>`8W1etW=7J6khE3G zkC3$4t5yGKzYlQ{Nr%Qi`kvhzI|kE1z;yHiragh_us3GrAszH@VEXR>Ory?Kgk1FG zQfT7T(Q*~arpLgcL+Uk{8YL6vcY&P`H2^m zBE~NvT|Dc)VKwnoEH@*^&Vbo|QVdOcbM#Oy{*IxbLmdQQkGrgmr${$^!(FPS6GVAGLbt+71-O6}1&JQ{$x8Xz)Cn?upiF!TE ziB;$u`iox(NaK#cO~(G$zHAr05l!`X1EjYc#TS7z9z54KAeEF;DQEKJ$R@@;oCU3` zvOWPthuqailXtSo;+ee5F!(3K=XwoDyS?>GKssC9dU9kl za$2T=6eQi?=(N{)u9Qx{;pksIj-G=RIF8MyMbV=%wY2C7%&b3B*${^C_#)KlD#DRo)FJk5DZ>k7`5;;fvX>y&FCrx}H>{Eg4T@jtGl7QK9yr;AN1%~0pU!#^_KLGsCPxu_m)nWrn}bvXlQrz zeTf{+>;2vh=njn0SGjL^;8$D!9R=$zgK!5n?Vs8|3*FK^z>#NZuF=IY$8~1;W$|sq zJQ^C~Xbt)(qOLevIX$D`=P8jcYU>yu5&H zRh&6nWV?cF1NulKu+{t2D2Q<~@uVCYzaiUy5M&G3E0g)w8II8O04TT)|& zny5n;-%K6E$o(6>{SDv#hHrnvx4+@rzkhtY!V$klaBG~l6oY3m#osHyw$}RKTQ3Oj zwQc-~zj)Ep->&HD#0_#c7`N@GjKGxLoqTtMW!ij);k&dk(ER^;-@PB zqedC%P^_u&fpr{GqZQdO#Z>7PS+a|#pwT4&(Ay@&aS+kPD2al81#4ldwh*O*q ze_2Bg(us2-S#l4E>>faVufPw>vrldGV(V&<=NUqc!v%>9DQpYae9(4`x&Td4*z!j+P>W~ z$z$$BYOCJ!Wd+%0MBQvZxas$YqfMZ3&?=to2@~t=%-)5wl~Ps=l#@w;{2c5Fjt;Dx5$7NI; z+X&{~W}V6T2D}U^hTe#pt(4+=W{R1}X1FM5DkJ{Ph(Gm)4DM-9W_vHM?)j=z5gm!B z!`dueiAkgp{$SjGN%>r(!Vzx4j|29LDK5&^##0`CU_)>Sz=<8ED^R}e<=Z$IZTYET zBs6_$JyVSRt%hik)U2TlJWO5O>Wx}4x7Dm|lDtZBK*)4TCQWrF4w(nwXL8FBrXqpP z)k#`+NO@;qQI=UsRth5(;Ro_Fy0OBwq@Gprz&@^&k-+ld3cEC6#{f5QMHp$x`Y|;* zmoFw0h98y2{1i#4vk-vAxa@xZE<62A+ck2KVm3YGQ%4@|FpN-;6D(?GnIB3s(=&qE zh|?}WGw92T_?>c#IO%jc><}iDDo-`ze002pAM!MX$$r6+!^53eL8jAjv0USk9+^4> ze%sX~XS^4gne7zK@z^-?2VxF~Y(jTNOQUwe4*}Pmk~%;uWf4(0;S%_8@FkV1T9{*) zCL+Ma0cZo;(@b_DuMHz9VL*c$!eE5m^w@Ps5|=6jnRaP-A0nNEOj>yXe9#++GXQs% zvYRksXg0W+vLr4$JcMDpQPaZjCQWn2GPO0+75<5<>+wINDq|6xqpXbPA@eHYv=Qi~ z%#@BuI2Z)ojf|fTS%%>x^RdHihqo%)COZjM^EeKoUrB|+8w>|6W0qVi8VRjcrG}Z0 znA6V)>5=h(?}VDX5$R~yIa9YBZF`eR6z))2xO8HqHjhH9xMu+y@p%k`&UMB&9k>}e zmr50M_xMjd zVrG*!5=(#RnNTGm4~FsxvEeD^DPb@XOjTC}GRRXH8-{sI6JV6%If*uL0%g6Nh74H^ z&J_qEYUnA}c4-Ayp zm(Z@|Fg&0EP~CD`2TE3>m#%r@=O7&8ku^NlrI@Z$rG1_zW#hp&s#1%Cw|*BmFGaK3 zY$X)bQ2?EFdV!Bzb4~QvvX_?0z7&yMRDOo;)>9md^xcuIqRbu-6knyB=HsNfG4Rtd zG|f{(sN9pLazqe)WMh&LNj5sj!sXNDCxTP53VISH2fSMe1noi7negXs>mtjoP`M>m zNlojg!qe&9vVqAgF4WS++%#;3ga_;lJ*Em!jlvWOL8XXCI{Lkalwv?QI&uz3!IN`< zzN7OiAlFsbS5sYIT^zwtquoBck*9!3I=Ko);UGf~*41nYehyHfLlBg$E9@Acy2t=^ z$U7DZq56ela_S^U*e*)l%xu@NLEjTT60x^mX}j*@>2FT1$#(lHrBR9 zLuUStvJhNcZjvCm4=D#+IPCBWbm(_O2%1#X#V54u`#&8yq@-{b|Tt8?s zPYk)T!*V5onisPnRPbvd3NaaC@vh*^z*7^j-1AbLKA+3N7OmuUUdMoT z?z!ckj$>)PdgAj`(?1u71|#{6%O)2=!dI)h$t48`x*%!J0$EZb=hm&HP0mG7oa-}E zRu0SBioTD$;5~6ip1G3u3~g0TE+fI7mv@rrrp^i1?N=7HS72t4tFo$}N-sOhdS7c- zZlK>S?LbV;Y2Q1*#hQ>yT!U9|V8TTg6$Xks525|Vge{7oj$3hnX zrKfsX)VK}>*@_-0JY+p;g&Wvwm1GFB1@`(m?8VBA0OxQ8G}SC%*;X{_)s&(q zrW8u>LnTa^f#iORwla{GJI8nG#?ZrzUd%Ldg&ZnQ?%Y9h*#eRsZ2Y2gjIYj;Q)>qY z9u=T0)~P%mGhgitBRA3xvhht%p4GcCX92|vHsydfd8!sZqOw0wCb)ps-Q6 z$`c46$Gmc+F5k_|(@~ov!isH}r6ZG&RZW)dZBuf~cT2OZ9c4G?YQAs2d*VW}#ZD}* za_g@)R#D(^D>el=AN+yyB^47EtM}wGY;p1+2R)|;g<%GHfmBnjRS`Ar2d#lfOrLe6 zjiI5=w`pf$tK&NZv)AIHwNICrt~G&$l{KrzN!}!~4!rKox0{yP%a6a?I%xDl2XSeN z?+4)hm#Wwb7BwyuAz>%sgZP~DY;h6Pkx1Y*mne|&Gsd$$-sO4o40T%C(?aJZ{-VR3 z#Rs!&Bj?0FptH%RgY~n?5)o{Fk{)VEfCGPZ z7q)U@ZNHU0Aub`~W3xM2xQHV)h`lQ{7G~J+86&%BvAQ%`;2*s@1E_#1JvFw$fA;+G zlg~32BqJ+)_3|vKtYQUvFCKTp`;}i)aau9B=dp&$H!o&(ykD+?}85GSf*l6o5(4HA{>FiH!>ZX&-Dw1F_zU z9o{e~|Ku*PV+pBRoT{PF67z)BXi!1taaBF+jNuwVtrTln;BD1(S)+XXj$B!Qf5}_Q zvELTfQ^Me0v_0;yDvubvrSg`59_?(kE=BTbq7I}|0hU=utwn7|#JWKcizYC3Tnob7 zxI<^sJFw9(RQr7=rx}(9q24K}s`#jB8{mVHKnJd1=d$L(Y`7AJx$^U}N*KJ>C$Nu((#*Km!eAxE`dRV;EnUW5GLT$Sqms(2s!XxWw5$@w zN1y3_Jb^K@M@Zh0%Y!&2+Q=b~8M+R-N;|EGgrpW*67zdx7l(*)HVJ#7y&y{FSk!ot z>XNV4k>R|@K9VM(y>ny&2_uO_PKZ0C?GQvyjshgfLDI5ZMoEk1yeuXi#!#WLf-qOX zA6Sf()6djZO>v~N8YLz0>=c2GV&m0CbmZzWO7$RnQ;s1`XR#gylyj)Oc;qHGuwNJ~ z#yb1yxhwnv2Wb-ScX)yfnoKuUSjtH>Eet8%F4ez=d_ctfB-w-m`k25GA%=G?4li<} zWuI2o`{UIXHIIgTa|UPj1~eqTU!b}O*UBL7tdK!09XxIpmW}@>A6Ct2;#4j0PVicW z9W}EzxyCpY7G$-uZsf`3Dz{>Eu4-{CW?sEBjyV2b zqLjD+WGzAnxmyR$fKBdTu6QkxNtu%{!)A`S+eA#IP%ZKW5cB4Vagi^h#4dW46^xBM zYYFcPW@(^B1(^;d>f36OvlP)NN0~F#>KQ1~ga%a4-6bqbTg*sNAfE!oG#CM=5z(wf zBSi5sMNor&cdSo~gMR>lS#b~KT84=0ki?E`7F-sX;@`DmL{nmR1qXD{tQ=jakHzK6 z#)%A!%}dxvq?%XP+tCsc&?mS+KQb&6?h~uV!%)}`puKP zqdRm~wVtX&AX}BTc?x8!|BjWqS{WENlyDJR2FrrbQv?q%EKIMIyAy`RbVf)(Z4M=b zUm|c^S!-SXqs8On7?7ty7%NgkhdgFLS2YCMG4kzzSZWHZuQ{$zKt#9Ic5D&F4n*ey z#e^|oy(Q90tU(b{>KRacd0>=- zMKA^wi#HyLRWAowsw9;KkqduMJ|UdP3rZLl;5Xzyo-pb_Q!g0REf_Wiql=XtE96m7Q~=qP+In1(tn4Ojf>z9mYSt1_Nwkxm z#MhgoF!d7#*ze)OPpPPkH-m$zQEs0$%5g0N**4WGCQKcb5zt(j3ub54w6v|=Yd5pC zyReC7Nf%eLyOl&m1Y%f}_X>!>bDgD_IvL$JliK;IC|FP2N>HmjCI7#YYG|!+UhxdF z>@gUMU#0lAG_{iFiB?+IkWTsw*xyDn>%@{+$C?fA6KP63gLs$2a}y;&5gjd_V|H=o zis#`8nC7^g9&9r+OD{cK&reHgbx(bbNdW7_H%nhYG#k|=|LEKSsh9Y&mwC4)-J8Xl z^->d=U2#36Y&gZyE=?&zVDOIY3vWCs`ao%@>lhCih$B`{# zAY%=I1{|@YvO6lQcE9CO*9~`To&0J;oN+A2u)YIY?{ZzOEaVP$axO@5&9-CoQgMGY|G2OGz5U84qq{-fUP6kQf>|OATRSwIJ4FO374`ym>Mi z0fPkD;TVRjir=9h8Fea6+I@x)k(BHx6g-`N94?NT4G1#f2uLVcfeV&05&2RXiAJEp zMh*Io%evsHetnIRn!91d$`7lxvggiqHLts#UW+9Sz&1xuIgySt9k@)0^#y`A@on>W z+^+CXb(fZFd<~muYl|c9%ZE~K%u{@x6*0X<_TKYGS|Qg3c29S{hzqyULvd)g1bvZ9 zDD{<^2ElDPM<&+njN{jA8aQ#Z;*z_t%ITg5sVr14!}m!6EOfB~YL}{aspOjTnY9iU z>jh}VUfiVG(6I>`orM^8GLLtK!(uxnnPlKYB@klIzH!cPW`b_dii1gfEE>Kht4oWL z=6Sss6vGZp=4^lV@a)-Hat_eqN?+Z+<+OfAc8A)_B-fh)YcYla<&6$lT(kne zE2(r3v=JPlnM}C??a8LCrB*uYN)=24hOY3Ei=&=odbjZ%By% zYodaN#Pb|A-oVplp~&Pd0qE0DigViHvO6@OGbJbP7ULoJuMuKESoj2~@0ZqvTm^hy zS}~5{noYEuS$8A1c#Sw~*{j_@xIe4+!gxq%HYfA>d>UPrto+qVO7tS)+eEYF0y#M@ zG15vmJ@G0kt~p!u>aNVZ$i*GK;|?iXE8+K3z-+s$4i-OQ`~XdXlIOCsv)V*Rp-uJM zJO0F;B)KB$$~G&0=Om<(Lx7DT$xq$Nr;en3Nj-O%UXF%s6MN1G(W{ihoZsdgY}S6H z3+NuMTZIRj=hFg*Y+sl=Aev(#5HjP<^u>U~2KVx|172thP=fWfjYGTWQ) zhJrPkZ?$ICgdyk5uvLqgw}m+1CF3SsAO*Wk8r*TN7ns zL>uEIt;ugl_}77iNy&x@nsU+B7jv_7YfzZ{TC`%NVTs)fs>!O*>IE#l!K^?@gV+hK z2Zl?GdXzcx&k9K^jbk-blH_>!f}Z}#&WBL38fxag3T z$bM2)*Vxlff{DvHsJRDAv2x;bgYKc2bc(tr^))-oc8ws8n)0P7a`$7m2efNBNsdDv zeBwX-*9OKT{+~jFDPoRAn2HtPPPmvH&d@4T0`FSBc5Yv7Yj1XK54}RTZA~wO zMRAH71(ppXG|(Kp*m=UdPqsmJk|wQ!!DZKnzCxgz|92~yOUHX;hUdD;nLEWsX5W{x zVLiy)ok2IfU6ZXYi&3{{k8HV5?3%s(+1B9^52ZVn37zNVnO3Bj8>?Ek+G)jiOzK-ela+N0cj#R{Ia$zv@zz_TtYt3v=h`|vE}WB~|{;cTF^ zuVXxWQZiY!k6mY9N+zqMn%1Q3tj&8h&Z!kZ01uwN5wj$$KwF2N!teB`?^Km3Yap3g@^rb3h-7^d+$+~f z9hQh@JISWF7E#=p1G_bqfUPE(N~6Lwn!ZquBQo&{;HE6rOfh!X{9&EvGXhFG9c5FG$=apo8^4q0Zr=N(pG8`S#w^=xuEGVS0k?djg}K<1LM7v8+H6lq(#vp?gJs!0m7HS3 zSdi$=Oj8(uAn+Y3HZw4lc4wHi0Dz$0!_oCAfS@(2NKlIdz#IvVon0ev)qn)kKCLP_ z-9F82|7!14XiEx&Z5*i6KARQ?0`H!T16vgIvv6Pwix#oSr^10eei2-()BE{2u;JRc zcsP7Q9N6xXyov)c=2x=neQF@s&PLMeX3lc@8xXt$5R^ekeIfxzzcMIzqWUFrZ1yLE zf-N3eJ_$Y<6g*X@%FOm@py0AB?Pis`3c_IishVK$R+=cEgn_QW1Mtio1o5HBKQD2C`2+VETWf3EZKqbj*`F>N4i9*0*!8~k+kOaQDLS)S$c*flv@rF zTUae~M0nU0Lmw?x**#5l%bJ==38VDPXl)0Q+q-83k zT11cJb!msi!Rrq3>LHd@N+mOho;oj_b`-75* zJvjEQhg(X2K#F88ETW1rtY#iGmxK zi?f(0XIo6X5)-A?Qejyyn0O3{y|()tN+v9o9fD$~k{&{$Y|Ln|UeAQJRCG!?)24J) z4Tl1xyxO*fCOG9Ag_eB8~lj#c`4A0RI30ABzYC z000000RIL6LPG)oL^SPvS(6;ek=}Fbx73s(Jnn|!0SgRAG$Xllz_^dJ5qDNg(`rbY z;r@U58JQWGkyYL70YDNm2^v;*W?X)J?%_v^>B0R^{}{?8w#S+uTYL22>&0DaZurPO zg1^u|kJ&xCOLmv$+>?GUE%FdCU7~xeiHE@dgG1m*N#1GnPJ7IO-U%1)pvr?l55nz1 zAfHdlzLV+qd}+<`q*9?twZfBf_ySHUmm=>(dM6Iw!f$)pEAO3bR;=<;Fw= z$pHUX!t)n`u9*os)#GK<;AO8I)0>cv&yAU&fxJ`cojRx8@%Pz64(aw}3wP%lpEvHf zf&Rw)Z+%}`s8l!~clb_e;rI-)o| zp7^K78)cGqJP6-5gi(Na1uiWm9it(AGl>U>LJcZhj>TQgnU{{Mz;R=sS5l*e=Nx2H z;DS<1q;rkHv<$lMg+5jmk!GT3Pp|(2aP=yI0@-@cqAk{pX**{r<=Q z``v&4zt`@Xa(VUUcdx;@SHJ%8fB*Eu5C8tBAOFwWKmYI_|MB_@cXiIUS8smxn*Xan zeD&2gfB5eGyLVsy{x#HVEw6s{9X>0eyn6TbYY5;H{l#y;#4qM}P4U&&|N7mp-~ame zU;g3!w{L#^yFcLn`0~~7zxnPr|N8EAxYqFM?SK90FMq)iZ9+Jvhw$oOzW@1$Z|paJ zP4(4pfAi&f9`rxoz7Dvm*BO6&_07B2K3+q6_3mHrx7F8ZeQ)35UX6+7!Gwj zZ2OS@UQOTW$omh?sAe*wJ#5HZX{H0znzp~&glgQ5JAQvMZlVPwAi5`>#s61rk1{O{ zArXzx5R`-_Lr3D%==2ptGCsC8d6Kid6KGnY=o6Qay^4N~hKc!T0<TP9EQVJHLV^snXEVZ? ze5g~}IKWJe%oZ@)h}pt+2rX=o-a;PA5`>=dpT|fmj`5Q9pzSzssSsl=nopyV9SZGB z@KdS#WCg{uAyN%)zdf_9e7YkF4oh@!Ar&R3k zFwb5t=lc|$%9c)blifRow>XENel9rz0_*n=ZytQg&;r7~1>GXv3j}XNxC7t%7H9Yt zzf)WhcnfijZ4qK#t6*D4$kx|_Sl5s(+W+|G8MMvU(vG05YkmuDzwp<9e`??sVp3#_ z>)&A8a*bh&ZSk*jya{bR@rW;UY-E{`;y`OA8SUYdzyK+>NH)tU$;cb&F|f>wk*QT_ zfV@ul578wK5YZ-64y7;oK;z@@d2n3Qwm0tn{mHi-x13ubHPk)Vs0z70~0U$92xvfVb(WH{U6a@-hTMSE> zQhU8*B}BBhiLA1?*gO#;F#;VgqSdIUiv#3GpVj+8i}uH!-rGpmc4OGrav^`D_L=0I4ghXI zk-zNN$7xpZ6zU$!Ej>?Lugj-!;Fw{{g*>i8>Xj)g+yJ>GdNOeV?brnrf%2a}(jTKx z4l4A*g&ZOxi(Dm6LMb*k#XJcK?^I_&6FuY3pfyc~#KeXnPmW}Q8<`z#_O6|OV?rJi z-J)V|q*gj4-gy$W7n9JFRnE|^u6{Pd9fur>a^dJ;nwP!q0ggTUw{Yz-cZ!xnrGWpp zMqG&la=x6~p~h`CSz83{XIX?;ciaL|47uy@^PW6*19J|P#$dzClEI5U-oX%HhiP1qKt|hvia|h*d5% zLSrH+RmeFLs-mk(LBxsp&n_bxu~`d8lblQ+#W30PIEqLTwJc>xAIN!rD9up^1(;L($6~gEI9Rc$<=3 z#}H&wY(9LDZeH=9qbD?pax{rTBBA($Cz%$Tj}}Wpm)y1oBtv4b#)Bu`vFvgCw{W=? zAvRIFkPO>+%P!IJMmyfctnkD{nW%^t41sqE%@IR!6h%Oy*NLLw$H71zo_Hl~#9IQj zG6k0)T7h^2|2d>6;xOg1K(t#C&W{-=eImFpu7cgFAYiF%5*^a=zwO#BX`zz&*(#Co=s7%4UvY4 zQ-m?2V4)%3(DTpbsjsL13AaijoZxTR!q3Y=xL(Av<^%2wRc# z4WSCqPBc(4HI_t;DMDd;K=0;9cZE6_cGqD(@T$U|GMGR^>)NPFkcQ&!MyK44PI(Z` zY587mq*P25RkkQ04u*1}qeFV=@l7T%E7>76tq7MMq$5!}m{+SqBz60kj#$TTb%!0| z@GjgP5%XU3H9kA`#@j{eOxfWcWTABVTxE~~u0)fpNawyZu^0)HlkqNGPr^eFW8|K6 zL4x(-9;0Xs<{otg%)}=t6!xLJBh5QgdJL9Gzv>~D#8RP}m2VqQXVuc?EphOOmg19l z{+1{?cG{D*K(0z*S>ccs_FNfh6E{yPA z<1cI$8jAtd;C*CxpU8JUp!?gg7@kPE_>Mjt$1_4QY6hle@htizda-4Zae)Xd7{#J> z=~L(;I2EI2JhLbYKi?7+29ZWTZgouOf}Rvd0;FPG90{*@mBUPdHOEtdFIt`En009~ zM^ij=fV=_K4#ionXJ}Fo6=@@J-FZYVC`QbuJ<<2`UGfBdB8iHq4jx%=T!0-xP#KIu zwSqGT`b%Q_Q?VK^iQF4%!e!RLO??<28{4yBk7R_Y{EKXaC5>yuNf4!pd_??Gn9_oX zZ}Yz_(McNdIK%dIOza79M-+&5Cjna2S#ny9NjEh0gw4%XVuwn?Rwh|N^p?ye&<4}| zNewo%n4|jg5((pUB#h^%zGOxTLC{%NENBXbUc;^IK@L$vn&vk(Cv$iXps$xqgw_<8 zgE$$|DbaW`i-_}eQ6;d^Y`3u=2G1{>*Saq+q-fKNxvwgUK=#iD^k?w!1kHOscy+@h zF_xmAz_>Z_fL;iu#H)f1XTTgm576vMA3M&p+>52v{W;3**F!cidy z%u4UnBkhEyQ>7ayInoeC!aE^^9u76Q#h(t`z1(#*3XG9!_v{gIbYVo=?DZD5 zA4v?lr=oG_&K5PAFn`LFpb~AI8Ehvjxmo}}$lbVHxUvmH8d7{YW+6a;zXiERR2o11 zTw*|w*dhY=HxJMtUQzFkanx`VwEHW-c^EbHFlryyz&#`E4usqDwZufYJtpVt5^RFD zL_Wpsa1HqgxF`I18*CD<4h@i1BsEP%&^v6RO#<2wTkMXL$agsA=eTX|=$N7Q@$&Z` zFgk_oXM*7b1I)cM7DK__b-w~NF9y`lzxH&XK3?YX3}AT2nE#h>zn?B=dIldGpN}g& z)OGR%R^j3=iOkQvcXJpx4PSgYM1FS7^^xKD88)302q7%~_h=3;2*o{70_}lV%_*=0 zH8{8d#!)2Ejh))EvGCPJE8zozar}`EupJ%X$426gt~BYNn{w%Iz~Q(;j?g$nnKNHH zT^#Erz$uvhjK4o9{$7P6)01_e^~+)Jwb1RWv`n&>0^aMb-0kr$yhda7PW1a!6h9Mi zXCT1sOHDvIp^&xM#Jv%d#LqwLjdOD~Z* zUg6T*U5=|J7LY}2G)&Mt@E7-%2g?QykbC&d^StFDUIdagx~i4isc0eK#iFl~Z`%cY z`M{p?zz$4xV->cuQJTRg0mONBNLzX{ADmpa>ZJ?$2SdMvNL~Y=%FCm1iVY+!LGqM0 z3MzYSlUL9%_mflT3g~{w4L98xzceQI6v@P4WD>pTvP5CEPXd;+EGWfpq#=4Iks0lj zVmLs6stZWY2sn^fHJ$s*ddcUu;0Z8Kmsq;QlweYT^dW&cM{X5LO%S?t90mwggD5^W zHs|{hHeTdrRGs)$3qib~n;h3&C{%(s4}hyKgy?U1$HgHe39w5pW<$6Jh$i17WJg}Qy7qu5_}lkCegESh|MQ3Me)n~2*OvbJ zXJlDI@`rx&8G!!+5He38JbTVdGS7K*5Y`1q8aciZ#Y1V=f?pxud5)!Z9Nz-{g+lf( za*o%1Rwi6M43Irt5$Uen5(aAmkH2`CM^7-A}&F z#d2$*F`x9*Pk!R@{e&Ima{+a7Bk+MdLz;m4C9mnqIYApyG0_bSI&KGu-J4ur|R4-F3xXaiDt1a@9zVbN? zoPcr;vj(rmm6r^qT()0J^tIF|S{9xO%FjHSXTEYvJs@>RNK>KQbI>?N5L0ZuWsIRZ z49^7P%Mld9t)<>`0w+M6=8WfWS>y<)m8l#>vmqP_J%cYqu)X1Ia#tT27NOmzH~JqN zh2Jla?t$e?<6wrm0@mOTMjWK&eK_Ki5ren&0H3 zujcgL3_>huNzGF?`KDyT`sUoeRq07>i;j98=#DOC@{;G)e2PW9&Cm3aQx2H;0lfGDEZLoEae(D723ayKhMT|mVdlS5|#MJo!sX&tu!!qu9Al= z_l(gj-XTQ~&jIAbdynaesh;B=$2}&1jK4OKL?bXxp1(t^iDZqUb-^uLE2Ia z3#EPhBw)EGBoSTL08$aAmp^?5FgLz6hLNh}XiFAJ))3+cxu{6W?NjGCC0;B^DmgPl zXEWhHgY%E+8wd6a8$KX`h}-tk=zP4OE^&Q9{S3$W_5k#lWt1FrZa~F2d~G)z<5XcN z8`c3X8i!xhr0B@e1(wb&HP^Ht|8p>U43*p*SBB;QA-ikcAoD;qOg7%{Eg+v(Duihz zZYt`M%@6K3l?p?-*2G@$tEX}*U%w7DmQ}GrkMO-LHMjF2B!@BOpAWbaD?<@Xeu!(Cxth=_Mvw|+>0xNOqC{9S2eu`>$_|Urx16m z`6P8yl9mSC!U4D9ak4s8Ufc~XY;y|Dy2RDTw0MY>wO%BN-dOZg?k2d=n0?BQpDO%l z{hCoNOlyXlD(R?<+OZ#p&%;(j_HUM~yHRhWs)E%U%2Yk>9y1jn5&NKYupV!DV@KowZAPh<}xw(kN`^%tkzX!%(cU2Ek#bk8qLBO z<;z?p&o_9!UxO=YWlv43AFEK^laz}&5Z$XHv)Sf%Y%{@b z0}J;$3_K8iJ4Y`Chelm zXZU+=KlT#dqo%dV_MR}!A5f253*Ze{^hbk?3sF?QLk1fzB(Y^z{Iebny*BW8-8zCxbOe|#y;$Nw1q9#j!{hleQr{1vEY4abWA2r6ja>wb&NzMi}}W^1U)csSZ=WUudS1;eTJ4{1tM*U?T(xa^NDp3ijB$*{}*5nk^&&HM9X zo~>ZljS(gjDwD07aJYwaQL1#h!~y9U^tOts25UY)`xDWFW&2Y zN6^*Wjb5oECQCQ^FOKuE-mL~v^=P_UpQ**Cs&(DaZix2{J)EdqpqE~|1Ekx8ZT3zF zPB_+TjZY4(Bj8&)cBZStoo(!FlU!ZUY^&UK(KY0bB5*di7&gU1$V-aQ?yhogiAM)LcfYcqexFf^T&x7?Sgi+(m!&hs|mBxr_crdzsIy|XlCE!t-yWM=iwXvM->?q&TUOyFjV`N>A~V2j=L=)_$x z?d*K3Iry!Og8`BAkHPh(PnuG3y368!7LugIS!0AlcL#uvp9R zU9KFpIln(PcV9(th6JY(Y8qZti8(7JA;c{JDkNSCi5KhiWN-916no>ir?#7VTjn{N zQ-m^BPwaOXgG+KL5jl%Velm#fQFa!|7!==aqnrII;K~9P`{qXN1BPROg%M@$7?P~U z(q>OM%1>(s^tF%ZtjAVa5G_F4o|HuqOH(ONb+r(h`=q&F+)fjGl}44taET zIMjJ3o^9o{*0jx*U=049 zRtm|}cv1`h>P`wMnv=GUfZc?%-p(}bDML|l?0o$0Bv}|>2qm|(hPGwbg~?*xrqS)$ zZ=3wGPPN*Gr*4v?9QU)=?4!a7dk}B-Z`#fwE-fw*KSi&h={_<+wK!Db>lwd6ZyF}S zc9K{bH3po5U}bi0`?*m>*qQcFZ%`)PPoNk2xig*VK5FZSx{J5oCR8A~<+kPd<-VY4 z4Vh^zy;(%Pv?~m~FE|$|#Q#sTcBsszCOlMbON(rG;|6UPT3nCz#;;NeWNqY;$kXj3ZrIi9i^t6H%#-aFi6D$qpn7W7l)A6(O;lzYsS zCxH^sZzWp4F1_Ir8Bx3n`>7!~3)LOfiK$XET=sg#sL^uxEV^nCWE}Pj+gC=MGUTyP zN{C(z%wxdkMYQ%ZuICp`FFg&rcUpu)dAZ{4sREu6>6qGg(+ucJ#PTXpe03a64M_<{ z*On79J0-W}kVCk_nM-&cv70F*cM77B927*ux)}=~E?66sX_p~;Fv#M>mL`Be>)+VuCn_mHFR3xx8HVM95+iAL6xx!(-8|1M-1cg+r zywKLy1b2Spg^t%!b_n{ec#6*m`jbJ>ZeL9(4(_d;6FL>#Q7UD}USKayv7}MTAH)w$ z-^KZYE8>Xeb|xWcV{L-h+!I#{%_J`S7t#$tL}dbT^xmExq#?KLhIH%By)V2tuE4v$ zPj9qE5$rX@F_7l=6VzX}Nc)KtrLwa+Tft%u?BF~6j@njm z7X;$!Jq45T_(=w;n9J5~3sjg?q6*?_chKMiM=1OCv_c-k5maU&7YAV|!KjJ9Edx>%Jn5S}*$tD!z6P z=B4PVJaC{UB}n^Buc5FB6D%%pz7GgF5V=rwXkiXgMfe^V*%FMUARUqCo+gK6tJ2YU zXS53Em5jDs-8VbCsdct4HFjJ**ScS2s%OrVYbb65*&71yDMX$+j0#6_acPhQQ@&#< zsdx1QCoMj+$cy3xj7o{p<}@TIogehRR*`%SCq+Z4Xp)+q!37mfRDcOhKJZ2Nw{Z72 zl}$5y+;cf=+@x+Vwvq)PX-#k~3pU$}dY{^C%?~xruphOAwfZ^Rxk0?TdL?Qcb-|%wT(bxq9OxWY8;|4U|YXu&>R;yW6Pis>&pD9lg^|=D$A1Ln}_I=USMb9 z`0{mY-|l>C_WO>BqcD&Z_D3j@go%Y-QSwtYdks};jXA+2MG{`J}tjb zp;`-&#GTCBO4;~6bJ^JdlWeivJ1vkLXMI--gYX!e&Vl-!h(1SMP2jEXEMjwk=Ye*C zMUE*A7tGOv+MnVpoX#ANli;PaEXeEw^+6#3YT@cSUdigutn!d>O)^sf$xPbIm#(IK zwDt+n;W>v0cFu(wlxt9oFO?&~iwpfBHD^)(mo%A>iv_k$DDWHqbx8>&3aU+uN(ks<6ZfJ~n<0DYAeQA@UMDQcly9F@u6jwxRV5J*p$?6lQQ*pX#H z5f1>%x~Yk{Hc4?l2$>7o$G?mgX5+!bI(8S)4h<*IB8Q_Q<14#04wKb7;#sQkD^Z}i zLVZufKj~|hjSd>Z)#Ma}QFD^nfP58MFvb36s){GQk+wyS2fD5SYK>xq2Ephh28u_f z8x(sMs7X0*T0*sl>xJc6@&>X}F60Vbv5WT>Y8EI}Aq1nOEjLRVFZJfpbMTtq014j$ zN@S3?{6((4SlVdks;G|EK=h}rVsOjENzJk%w@S_kifCS5EJE9U+0#W`poUnf3u<&~&7VLV<*BHi3;1;fbd~9> zIK46~{DhZY9lK!_Sp#+DG>bGx#9_%n*QlkKt|faK`jeodRiq9%dPTJElpqZp-RkIi z1`SBN4=-g#q}zoFfBX}PsgK$EY7}iPjPkgxCPKi=T6j_0bKm+#1>$8dcBL;OHB+dz zvZ$SQP_ow*RzPxzy=!SmOqQ;|PSr%5A!MU1>i!h+OOOO!!!Q3#|Zea@??C!L^>Mk&#Rub5S> z2PDQ~4bAY&k6!#sIiL|A+j9QJqU(@r@f+k~m7yZ<5^rE3#E*X|yA(xJIWu+n^dl%` zkoqU0&piAsS-p~)HZtsADNMJ=E~Vbe$nYD;9Dlp4QNEfip5G7ouPU_z<}N%Kn3 zSuE>FCASre1@6RH6pw3*A1$snGnS>MMpl9>jfQIKgYB2}*0U%nGDBXLoO@bP(jJZ5 zDDt+uA)B|Mqnx3jN*`4A@B+;XoM{-1UX zAuXvmcX;C2Den)w@@%Crk``8~D`OZxPtmoIOC+!lak>@83AWyo-&F@u*P?r@2&sl8Vzm;3|JxX|CVuYE}P!Vl# z{+=5x-aZ{2tiq?qag@?)#&G>HPWoV z%5hpKgFRpLtfO4-IITH3yXa@zg^FD9)YJrYDi%+AAF|w*V8qPuKdZDS7OuL|#9c0% z-iMK)Whj;A#Wqc|zyOxq?y%KbWgQ`3p*b!T7O z2EmPX5U&Ygm;i6I%-fJw{IR&F23%f+!H(F;kGaS3jw%OBu@898f&xm#V1#;Ev}Gwb=fT~4`Ytk8kZ7* zWnUu@2hMKS!Nun#C)9VZdjrMY9yBKuKRy8O*zW1y!i>DcZ&0r%MX9V*yf>~y;_r>O z7l|6kPfl&Uy%sHHR&MqZUAYG3%YMr}MtD(F4FCH`Px^f>3)&7!IM|WAIvTWwsCUu2 zhyswf6~|AzCB`*yL-Escm%*8=^&VeZVW_z`Tn{b1bR)e&>3vPholD$0}c^dspO(NGGIorM3)5NT6_n4K*x*_!_#4 zi;k8FK#>P@o^K3<2U*ixU zOL~B)HF!C2mED=jEU{T^gy)EgDpp35Yi!UQ5hs93-dPFMCCn(ZO<9e*R{D@owbR-S zo}-ph?`vViTIhF5S>XX7ExSAcrmRl7QRcanSYAMkI;&}3s5cT+J7}VAaf3=r2e8s= z7is&>`08S{dyczdlW&xQbp)mO%vM*>G@H278 zDA-6zFsvcf+?I2uGOzudy_gA6Z~VwCOnO}$7#@n7pzxMtm9^4pmv=ZdjdIAPhm<9kts7cG-1#KwvRihG*R1 zkWAE7dZ<*UmGsoGvGc|*)(3&7>j@~tkaRmF9O?O-=x$L?Bw7V96w@q-fkuJ4BnEVR zV7(uEkf0N0G2oDNzVx4T9{os?#Rjp!?Xm2!@BED3r#*Rl>&{8@k~J_H(eoPw&}Zm5 z=9fgzwS8##+zdYls!#Y5_<0*=A_-EKjY6<08R6n~Gj9e{<1+*;SJeig5#q>A(3qom zCx(_XBffj~yeQ3}xp9P|?dH31%t#%Y81F(2DKG>SMmN6Nw4(0@qg9~=3Z@+{b6y5V zr$wnny61_8M_&d=D=s4(Eqm#+LM+Pj@Et`%ssgdn8c~`zlp_BTRR&XO%^Qpc$Bune z)A<}nYotEGXp^rvwBj&COg)X1+)P0C;j0kkw1g~LQCGg<=v(Kg=Z1zxGEVBimfMwE zD%df8X6oh}U-4n4rdmIqA!xoCO*WGEe34mOkHX{>EWM|%8jspDyErsJt|hWv)ZZ%l zfkaqV5EsFbMkh~kv|}9Y3`P^Lc#2DIyTBCJs0N!|6QdU8U;&LOli7pC$8eOI;OWA} zAgj|vDoPpD{w{$7q@!~B69F|}Ag5+=PZG*d)G$O1N|BaYYA8s!M!(eIvp1|yx-!)s zK;WFkYC!eCaA@#>o+E1xB1&pYJ{ei77$9Ix5Z;IuB@9OdGIxR}giYIu$J`sL zOyce->m+NgUEmDrG?3|m6SVP-Zd`ftvP3LI&V^8n4XvW4(3l0iujsz$z=B_4Acg)L z#8w3Zip=R6wyK*rb1DJKa*HCVR?e{{av<4A2DPK(eY#{Fhe?irwk9uEz3TPM!?Mfb zXKklATU2FJpsjXMX+vh~hX&fhAIao|)8Hh{=fGnk50XNbD1IC7tATAUsgN8ykjR5I zG%(tOZOSlEuwB`ni3%2OgKdshqyuvUh}eQ{uC+@Wpk;VD3|=RO`X#PVHTnNb=@L2U zqXLX#(j?jU7XjQ63HSQ&{^6?!+~g}R9g*#~?|=IK$3On(58wUn>(;I<{q@gyJOsp_ zSmiLZX&ebRzUhG^E;`th3y&1TjSw7ayF%kWj<}VG{d=}(y9NW{UlftRTiTW2h%t z+0ce;r;h6xe(gi-QVS<|d)DD)3bs4Zk9`cRG1e}TeO8intfHT{cKR%Ze!7A&FLQf= zxVpyeZAT`ZU-p|f=~FVV)He@K*p`P_1t(11(srgZ@v|e?SvD5gjT(M5%xWIMa#B5S z$dA9-1!i_o^9Tz|Chd9tlWSu_KAJFXu`Y==1(6RFZP&OvT(dvu5D3gA2CtHlXn_~= z(1Mc?k13?}9GQauntf49J44R%05qw(37Kt6^K^x*T6qecDd!Z_pi*CM2xWW2v151( zoU3%s2+Ss=OmQSx@2}>rX$o}0(K(~SW?(I9E#_c1&`B`DhR@bvNI3lq1;(@6nB4-G zkj$2!2eaI_)^(i1v?I=~hJd5vgW~5ShmYHVMzD@ilLk$jSgXy&{I(8;U)8}FD~9!I zWxJ*(e#_1ZKP@=9vG>_agl3XdR&8gni80(vYtmk6>XxRdqjjUH502~UK+ETV*@7^D zmPi4i!ME*EO}a1b05gdO{jpF z=G`>WvYs^3SxSKCO`c_ngiyJ^IaDt-4AZK=In+Yc22bOx-9Zs>G{Fa~9Ihp;+MDMd z@zK*Pi`N>4VJML7lWhOsB;1C23 zF5p6XaleFD@Nfa2UwtgEt-S`{+QnT$j&$3-26v%9uerXuORg7r&b@m48UA@K4sR5P zH>%s+$ey0?mnLuWfv$(wOb=vtY0jNq4|F}?^+MOn1;ERTGCh!AbD$exd>|xxAiY+= z>y>&1>A!jR0xtXDYJ2(fUm%tmA-eMN?&SmC2;th&%eQa8|NiB_|Br9Kf~$M;_T5+T z=AZxHzyHUd|Ls4&`ptK5e)FCC%DwsBAAbKY-~Q<@zx(|k|IhdT@Be=F3wMpBym|ZE zue@__e)Y%y`R70U;a~pkkN@l4pZ@T#|4MhA%jwPAzyFH<3yP0#-hcN`-+%b}>u>(? zD_^c9zWMv_>E4^K@uRUcp!>i12HzLsHNu;3|Ka;zefZTse)CTse)slQzx^lt$2V{O z@w@MT{SRM%6|X72dH3)C_8ZwymIlzWXX* zr@qSc`R~5|3epun|MlPDwN3A8$#34h!=WhAz4NXqHf9!X>%duhY~)cnyuNw@Ykg_j{l4x=)wneZNjK2kAAE$V7ihsbBXbeBQmL zh}ToZNfnU+x()}C0g?>J<2^aJ<@@!z_w*kBnn=V_xzyAp3Fy0k|D*Op!>;*LQ6-6Q zxPqux5q~YCK&=EAqZ57Z*XgU^Uqhzr`4VG)J2f6J;YIwY$n^Y?En^^w%UqHOBR<$?pRVZotu{ z>n-5;wtgeh0});uy{O^TC23Niu?Tgik2VtxG(;$wUewxZ@}>#NVJFTyHmU9vV4<-o zk<_|dOI#KSr4~YcjntHwZiA_lGHF;(ZN!m3T(^F&nws99)5b=~iwZ5sf;IwRZ#(AM zGFSFNOya(!vp9%+nmwSQ&Ty%&t=FHvM>W%|IaDK3JA=Q(8uns1fA_dvrnw}$ThQ)8 zksi~Vpu9%95i5?~zC~kU=#XlU)f`I?BKsbZAq3EYRf&f z#8XQq%y(FYhY!R>(-A@L)D($!!k4>_H}eJ8F|H33yoh>~mQOmh(ne=RcPTa~Woy}H z20|bnBzTo&ar34uWHH6*u?s5n+q6ej%_o!G`qpmtb z0~{dHPG1Z|uwD^G6#hYX#mOvdTjF}9ANDTu_4&J^+9zWO%lXmGvfn0kmsEwV~tl2#^^z}xrsm(_3Srwydh&ej4kqk zeE$j7Jt%5041eHrD0IC~Gf?ORCv+=qDRj%Pdr&8$(x1hl)(9M-mfMg0+|Fl_sO8oA zG)UAspjjeO+7n#5oY796to)_Mb_zxHdZlr$_;_%}#K2B;{wgeb5M!}h&tcKA2{0Uf zGZvjOWR)JRu_#cVXqy%L8C)fMEJ7IQ%K;XH_5;JwS;~XJ=11RCEF)Xmxn{F8?JOj9 zeLcqsVEz{eq|?!3Fo@#Ay2bQX;C05YwJObY_jN-t;6rz?oaKJow_ zLO6GR2KxXW0s+!^jjeS^TEfl!nXnc943qk6Z3j%s?$5&!d>Q*} z^A%v@A@z{MEg}@Wqa*m!kWhT_(MRfG2BdI}IS)Vz1C4q}J3N}NVG0R#cm*B-q$)iU zwA<>(0aEiY(~wRL7EW|nl_*@w-vJQ!P6}pCZ^0$&{f0)r=d#>>7kRY9VKVx;r; z%cM7U`UGfkP()AYexyWxBp=Ve{3I|n_XPTW4WWy{T7dg0wg9L#GmrV}rWmn$50;v7 zqVq8L^H|_dgG_;RB@RMjhhQd~f)k)3kt0Rnk;C3mRAuuQLyzY3DYi`8yazZOfX@Kc zdd~!#YMy}TokegLpw2Ntxt-2|2~V}1a(!&0tvR;fsRb1@FkynH6KIhr?5Dx0W@5}S zq$WB&gi_tv;u*SZ9Y|yX2t)s@*YCXP_8);xkNw;S^_t>3iIbsWjJEXnfZ^($V^#;m zS)K0dyNxdzLBy8Wt>1D7hZN*q#}N88-N<=YxnVKq9v3{k9tRBO-C`ZdmywoxB>IL`y!o#hsBd!*`%i zERCQf8l7;id~cOirto(Ws@>s73lr)Y-xH3Pp0x5{*q-jSa9R z07_?}^;^a*imfOYY@0^~+US4eDs$qpE;OWNHKc_aURDjSbf>1<@Z6%HImX|u<{LWv zfR$ubx>Z+q8hxs*8Ud^%@$c$hVtbLs+@{CcxR;3CVDPqn`3%isT&_M-!ckFj8&*6(&Fh2fSJ;hoG|4JNR(v&-UWuDBs`I!@qCR(r(KnNc=5wHSmDP zq=}uGU4L0$=e7$paU+sOTSl+o(j0MH<7jf2d?pdf>~p@$>f$>iyT-Av)~y6jW6BSw zAcZEqtR~$SF8i5C;}(}jga#q61|iTigtF++-n_W@h`H1j9Q3E|&gErjU$WnOmh8OG zgAudu*d{4cZ!$|9ex__XW15Nk`sx`}aFgoQ3St%GR^O^Lb#`C3qFXtZ07T4~Q ztmK6@$z9VYiLX6F;{aI# z8UVIX91wwXI0IZE6hh(@1nf6R++D+IJOg6qd`$5ofSu+Puh4Gs3;^mr-Ur#nYpApL zIEF`@$5sxv?gb5}?;*k3Mg{{$9(*N+%gA0Zs+ly0c_cU6s_}?bbMtpZ)jE2#F{}>D zF{fBujpK&XY-uYy*>Jgi^)65s(eU+=ry0cWYtCAxQOV1_qKQfEJ)G49dnSQI zjGpL?%aO;;i7BZx*7Zr`a-zpI%=92NjOf!+^U4ai`DkPXFxE*cX||E)qW`~1ZY*4a6@(W^hBD`IM5cY z;Baqn&S1H{X`sC@?}?8c+R58?3vS~&5I5!O-cCriLE8B8w zHx8C%OvxREwpYWvV%!oU>{j3w&DyJWIITroZ!{~G6W!ib4HB(GK%7O*Vjn*#x5*5U zhU9N%azO0r7-Cn1mpH`a_l6cr33EsWfn@}g^{$^A(XUO_McH3Yn7Xh>8(bYS;^{3% zLd?bA{M$bItIubsI$w`L86378_n6p@= zC&WLEt4~4OPYkPVM2q_rVvu@mRRDLsuwClHj|LC_GP&_G_oZ9dCOLAlTLr@CGF86#n90&p;xi5ImTZIhy6kzk$ zIu_x^JD$QI>8=*U?kgrp$7C0#r%#^{V*^Pn;xR#s*e>pHj(wk;>F5X{F1G>_4?Jif z%%{ZJtmZq<7ioybAA&(K^*I7<;%1?sC~Rh5oYWK=SN{cR18H@f&hG83tkbfDi<|LH z2S6#g;?&e1@#+=5N6zp|_3C@Dit~Hm-s+F(5Vyjbep+|< zXw}rcFNl45)6TMN0o*49?1&{UC8IG;^q{*$B0((-ZxQv9-auU9D?iFEze^3R#?J(} zdvaBvC`HKR6tAHx(H@!_%pG9$Z)WZ!alrKL&cI@XB;S@E#mTj#9`x z{xgOS{V0wilkw%z3f=C8Dj|y>1LE;NP_9u3Bkja!M}|86weMk0u8 z3lwQ+M!CRM+mSbgDqWh-Uh=_OMH$2)z1gAas#07aD8Z|~+iCAProA}j^ma5*v?SX| z9BZXWD6b9a0cXAz?h0=OcwuH^K!w39`drp-C-i3d*z4 zo<=U>s=yu=x=+8m6qLwzXM<*8beeMD@ocgspqZ~JOR$Ii93*1K#%=>i21y9cZ_gB_ zptQ^*)`4#z0muHisCmQ|!l$vuClih}(5Muizzm{VJ|5*CO@?eF_k2HuWO?g_ZRUmS z8_j3SDt%^*;L|vtm{=GRq5uFnoq6O@JZmZcz6X+#dL;ep;T-S-Mf(sN9HQGq zoFJ%WgYYvwjrf7J8o4BTbO^g3h=Lzvn$f(X5d{>G0IbHag%$2(udI>(#xFd3-`BvO zK97yb9GAx1cV?Cf0C+%$zfH1deiZaiNi;auID@gr33YxeY`P}Ff5IIA@B~n@Ru8lU zR@1R0(O@TmOglreJ#>3^7eEG|{GiagBAG#%5>$o>C4$q*I@ecnw^;M+fXL%e z=ax)#_&w;{gTKc6ap#gH3Gpt5XU91Ori8je@PV=;yED9P16^97${2*;0dG}C@F~|# zrew`j8$%I%jOn_fjtglnm65J7-FP~@PfF6^nz-Qc61m{;O$&N(@cf_aT4(A*F>RKhrL0I)%(kj2-|)2ZyqtoMKj z(EANC7}sB3=^w9G`v2)){CRp=)pvQ&K?k1L!0I(o!0ZK$t)$jxa{5r@sAgRIC^iNS za3FKmu@}QuACx7+b)Q^!mPO$2g%B2vQv19!-1EEcvd!v((c^q-Im@mE9A|w%nxn-1v-r~ z?H24*AR#~Z0(@1u^vfk41(iMHOy?VWr1d2xNl#I?u)H&=UqUvyDi(eo)Wz%wn2|?f zYO5X#e9|6k(T)8;5G%;N&nfJbM>IKQ8Y7T&eT~701eYV#+AROu{fdfM zhJjfSHpSKYHPAY8AM@t|6jwq2y|$$r*JtaBrfDK)8a+EIva_F5QmSe3LyZA?`Fvda8?E4y1J+Ft!7j@4vjA^r` z=XiQ-C|pw^S_)T&?qGYy2P_+79IK67+$6a9BOe1M22E%69 z6@MNzVo&ziZ6Pp{(f*lyt;IXX(5fOz9p8e zchZMz;b>vVf@?$RxHe2d z2JVp}zF%PN7g+l@4{L$4=Gc|l_v(B&;x$h0X9R531*El3VU%9`+;A;Xad@hUkbVki zJGp+7+ZWsT@p0|mqZfs`_i0c&`PiIz27hWqtJKxtruxQT5bX%wRsv)goM~SW?cV~T zEhT9sU@B1Ndz#xF53RrNq3rA>jxr?_9Ky9toJWh&D~cCy@0}NAOcYSz$dq zy#EfA)xf8r?oA^2sYI%NKuZQ3szKaAvWHRvQab$bT`e6x6%3iHE4zK`=T^#f)qE%o zyJ0(&HdQjpnY_{{{5o1cmnzlLj5BYewr3{0l=f(ul_UXYI%?h6MrF4Z;nA_lT2@|L zDd$z%N*lu(M%7}*SCiM9lcX4%UIn@gWUBTDP#W#4)ph$6&P7nnZ(89cGW1$ic2Hod zz)H|b%=;+;cE+_!NPEUtosuL868e6iDMx9Ku&4gj_UAMXgA=WWPWM@ST1{ZxmvGsO z6UDw>C@hv<&lTFDRA^N@s*9veG{kclBSq0rhhk+SBD@uLVl*lr*V}}cho^p6+th-eb}fCtraO|RU@iH@wLQG4I=ox^XjHP+_@;e)7{x+dD4zKq*|WBU6U)M(IvI388nJe6mg<34{ur9K|Y;IgV?S&l&2cR%dUvNEFX?u*Th z^!y?Vo!B=_f2`$SH3RqW)|q>7uWq^z4R?>}6SrbC4Xa~@{Tj1o6H423U*_J`3NX^- z1Z(p>5?-K+^JvGGxT9-UFXUlH#Z_>Ju6Y~mzE7Ii#p3Vc`?tr?mbYl+zs+vHdmAtF zMRsidEDBcbW+UQw#55n=NV2|;r}ETRB|hEe*_$_vlQqdj&WvawMIU8+vS!;O31()n!2WC#y10sK%%j9qm%V4UQuySqOYn zI53TsN6@Zy974hrqhnE^)QeT^;*NLgdXT!CegP}%!d|el93&Vov5=NXNn$2LBDfq z@+9ijSvqb?tWt26+OYN>Dj)NEo{R)Bvs$g+TQ*>-2R5ejUeUlAY9G*JuYUk^Odpim zs`j)4@ApThHxw7ATsF&M9kzN_{EKC2YzY2rMYw}GhI@&}R8~hoAahR$dBfg&9 zyDdEwJNt8U$E^x%km_&H40dZ_-jZ<)nmNpfo<@ia4EI`8D*cmx5?KQVRGN*9D%THyPy6= zXZq>He+v?_5dAh@0b7D#v18ff6X$)E0Ob}di$AFG9M8t11D9i7=VUPaL@NW+My~`1 zC1x!a5gF6gYxA=U*CE6{hqUlZj>@BKj80+ZyE*TRjVg5|A%86t_j0L9^%JRvSAQsz zEM7wH{EOtAOmYa8DdCpGz34j>`X|(DkVY*BPrbj zfoo_u8WE+=-B5jp@9Ixb*kd9CSWzz%+tGf3&i?JjG<3p_m^yo6kUfxHv3bVR_yS?B z3#{k)b%}}fg3srQNv^K2>x;h#uyv?3DwG^5L>I9ya!%iBLGcqicOC-kK z?8+TI3Lp+D4uHC?{ide`%#D?D9gWT;$sE_y#x!!%IMa-J(?>v85?rbb4RJh^u*d*- z9sqwEfZ)RzPA@|fV&@v2Ho&t@YJ677@5+r^td%fSB=!|Qc!fu$=>S*ire&VOYDFm( zR@hXHLdGnK=|kgIci^JL*UlB~$u4<6;7#VLC%tXGfC$8Wp2t@Cidp2nS*D^`jXFB1 z#6!e}ZemC7yhf=k0Q~%gnEMxIgN#603^Flv@}lTO;as{UxP2h~woMAAb3+LI=f8wl zqAw`J90`ob`r6JSfq(Ozg`?AH+L`miE$nOAxrHm$K;A||w77}<_1DvaYw7C!A`ZfV zKgL0T-*|?(6%qvfE+w6?R45qvL;Z<%pnmT%%gC$n98#tc`q;+fb%% zr4sBOIr>r$QzY@a_;}D*A8>5HLy#=2eOWPF$64ZOZ7Oqhad}gyEozcUG(x zAJPYWIfs*`?5Oz?r2~-m-dr;}a?s}AODec4QkFIv?tk?o>#!blj&TGxgzey_d(iDx zi(gJdl~U^SNf;!s}5^C-o-F3fEhy+YmM68nu^thmDlCK9XB$1?eio2M!Si1O02K@qXkQwp)7 znQv*wxPWN8dUYdvM!(d;TO4ro*K#K;qOB6&oDT;ta;Tfcw^RiDwzlWV4OFOMjsx~T zBKl=dMc~s+HhApCEdGw-H?{1i0l?j{0&3Bj@p%vzJOzQ-Nk{@;Z#!7A@>0|q-Q^%ThS=T%*lUZL5??hPgP z4#??M*te37t;ljbky_#+@;Ds9HcEi6iz>w`7pu&LC1@}@6P__mvD?oyUzK>ydd9Rb@vtvT;s;+ zo11U9Sm4IN6M}I4H5@r}3C_lHfVc>>ZxGjOUEZJ&x5Umf77rD@;zPwCY?qamC0X2& z5^B)(wu_TWyJp4e2VC2; zRBJ7-YeldW?vJSt7mHmEu*9q13}D+MCkxQgJK%>rmc$Sno-EMDj)N$ebMRGx`d5Jrfo*X zK3~(C(1H3Gm|{yJ!cF#QtsSAGq6d!l`Qbz@LWJ6W)iCE5VQlm1iII;oXv8%tV9Y!{ zkT-lFV^GZYo@qm?u(RV*&f+>U6w5FPO=;D-zZ{me0WEU!Vs~|h3dY*BYR<31=P=>jd zZn%~k?xscv?)FuE%TYor+QGN%@_mvCDrkPeIifP)99Y(R!NF8d!8g!yrAmTMqBuDo z4zg@`Ez8cRkm$=LlGSsKZ75O>(L&&ii(*rIgL*M`Kv_-!7*O*QRXFX@UXd&+LMl1O zwQxAaWm15u#F}~za)y-mHu0|q;(U~i$hEH!0QSZw3F`fXQ2b02*jU^Skr-Ym4bjvx z?VmFgx4C*uEKZ^tXe-&LhpZqCw!4GJ6;uwV$W4pyb*M|XZ&ivp<3i9BNas8k?M!0+ zEgM9Z?}Ae#Mgt;C5HuIRK=N~-40H$O3bNF(=RjYd{KsN)pfRO02o{!B`(cCh_QwI` z*e8nQK<(Irv5`oEmUwCDZd8hl0#Bu!3Bpq2nr4V>yWu2pM1JYNtr!mrk_hjvEk1mbD$L(o3;S4 zaAUAiBn78(u(tvXJ^&gCD5!V3>hXZe3tE)^9!Lti$TKXWYkQXqrVMrp3~$syjzHnch{*FbcrLMlgW&vz_bn5Dg#d84#zkmHLsY$k z-~L+bNeSc;*nB7z*YYED7j`6}?esp;yQb~7X>e_y_fW`B_`FXLsOj@QX~7z4cR2)E zKg}`biQ#1bxLb`k?A6tB*Gxs=ajBdpC21F5u=bCGwa={lCk5Kn^-E9fdcxCVFP|?E z`@|Qm{=~(dkMMaPJKC0u^an!MXCnFqT7QAoKOMAoC(Pysu)Yb>fRkF9)7FCaA-L`B zwn4-v2GwWE^LcOg1H{fFtx|&ChI&$A9$fKjG;P3v8-UIO@(Tt>~XcF;s#~ilhLp**Y_4*+pa{Z9hlE3-7Qw-Nq&*P}`GRnlKBifEP zGL9UylATjB4!neD+f%&t!Pi~y`MPP-lR4`i!QLxSuwTBVs`g}f_TBitH|?3ff%iO; z+|IlU*n8bTsipAH50h>=u}O@W&y*YPZ*&)#f-?C|%=O}3kvoy!#;LU4MOL9sw{X2u zZj(%A;+yJe(L2`T#D04;2>PKU4|&|q;_gnO$SJ)Hye4gv9ZaM4~J zADMvo%JbJV$5FBP@hPRR1s;Vw~D9cquM8rXVBkdis31 z1G_m^H)zOU?#_3@4?QG%8hHaLe42_r8=)WagaWz&N==indKukF3VUuVLA-;mpRp3VJ5(gm;%12CejMzOH zyx5}V`6K@B5ZsgN!TYM@8%qc-3pB_u;Tj;|(JtpZZU}s+S0-vB6Q6qB?^Sl}%jsI;gDV`gG*m*6

;Gf?Kw5 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�lFhwOoR~^s@{z*1R@JtY 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 Y009360763o02=@U00000000000Ptq|eE +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT C1046::HG02024 C1046::HG02025 C1046::HG02026 C1047::HG00731 C1047::HG00732 C1047::HG00733 C1048::HG02024 C1048::HG02025 C1048::HG02026 C1049::HG00731 C1049::HG00732 C1049::HG00733 C1050::HG03006 C1051::HG03642 C1589::HG02922 C1589::HG03006 C1589::HG03052 C1589::HG03642 C1589::NA12878 C1589::NA19017 C1589::NA19625 C1589::NA19648 C1589::NA20845 C339::NA12878 C339::NA12891 C454::NA19625 C456::NA12878 C456::NA12891 C464::NA20845 C469::HG02025 C469::HG02026 C470::NA19017 C474::NA19648 C477::HG00731 C477::HG00732 C958::HG03052 C959::HG02922 HG00096 HG00100 HG00116 HG00117 HG00119 HG00120 HG00123 HG00124 HG00131 HG00133 HG00145 HG00146_A1 HG00155_A1 HG00157 HG00158 HG00159 HG00160 HG00176 HG00239 HG00242 HG00243 HG00244 HG00245_A1 HG00255 HG00258 HG00262 HG00264 HG00265 HG00268 HG00272 HG00306 HG00308 HG00311 HG00312 HG00357 HG00361 HG00366 HG00367 HG00368 HG00369 HG00371 HG00372 HG00373 HG00377 HG00379 HG00380 HG00384 HG00403 HG00404 HG00409 HG00410 HG00419 HG00551 HG00598 HG00599 HG00610 HG00611 HG00622 HG00623 HG00625 HG00626 HG00628 HG00629 +20 10019093 rs575534 A G 1686840.00 PASS HWP=1.0E-4;AC=89;culprit=FS;MQ0=0;ReadPosRankSum=0.353;AN=200;InbreedingCoeff=0.1356;AF=0.582;GQ_STDDEV=804.93;FS=0.0;DP=77560;GQ_MEAN=747.95;POSITIVE_TRAIN_SITE;VQSLOD=6.91;ClippingRankSum=-0.175;BaseQRankSum=4.0;MLEAF=0.582;MLEAC=1012;MQ=59.71;QD=23.16;DB;MQRankSum=0.213;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:72:0,72,1080 0/1:49,45:94:99:1352,0,1480 0/0:21,0:21:60:0,60,759 0/0:21,0:21:60:0,60,780 0/1:76,52:128:99:1601,0,2128 0/0:26,0:26:63:0,63,945 0/0:26,0:26:63:0,63,945 0/1:47,46:93:99:1433,0,1379 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,877 0/1:67,46:113:99:1562,0,1818 0/0:25,0:25:72:0,72,1018 0/0:27,0:27:60:0,60,900 0/0:28,0:28:60:0,60,900 1/1:0,51:51:99:1864,153,0 0/0:24,0:24:60:0,60,876 1/1:0,80:80:99:2926,241,0 0/0:24,0:24:60:0,60,900 0/1:46,48:94:99:1387,0,1268 0/1:55,67:122:99:2084,0,1639 1/1:0,89:89:99:3170,268,0 0/0:25,0:25:60:0,60,900 1/1:0,101:101:99:3748,303,0 0/1:143,120:263:99:3473,0,4241 0/1:148,140:288:99:4088,0,4331 1/1:0,120:120:99:4452,359,0 0/1:73,57:130:99:1685,0,2097 0/1:71,67:138:99:2067,0,2017 1/1:0,96:96:99:3554,288,0 0/1:60,41:101:99:1329,0,1692 0/0:23,0:23:60:0,60,900 0/1:41,52:93:99:1726,0,1157 0/0:24,0:24:60:0,60,900 0/0:29,0:29:66:0,66,990 0/1:103,109:212:99:3444,0,2900 1/1:0,74:74:99:2669,222,0 1/1:0,79:79:99:2892,237,0 0/1:77,47:124:99:1337,0,2322 1/1:0,127:127:99:4662,379,0 0/1:99,71:170:99:2161,0,2951 0/1:40,48:88:99:1553,0,1176 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 1/1:0,97:97:99:3641,290,0 1/1:0,149:149:99:5531,447,0 0/1:92,73:165:99:2173,0,2757 0/1:91,49:140:99:1414,0,2810 0/1:79,60:139:99:1682,0,2342 0/1:96,69:165:99:2281,0,2981 1/1:0,137:137:99:5267,412,0 0/1:55,57:112:99:1778,0,1636 0/0:29,0:29:62:0,62,945 0/0:24,0:24:60:0,60,900 1/1:0,114:114:99:4265,341,0 0/1:106,83:189:99:2589,0,3187 1/1:0,130:130:99:4645,387,0 0/1:88,72:160:99:2265,0,2622 0/1:67,64:131:99:2052,0,1990 0/1:82,85:167:99:2617,0,2395 1/1:0,150:150:99:6017,450,0 0/1:60,48:108:99:1505,0,1785 0/1:59,57:116:99:1794,0,1799 1/1:0,195:195:99:7778,586,0 1/1:0,103:103:99:3919,309,0 0/0:23,0:23:60:0,60,900 1/1:0,100:100:99:3686,301,0 0/0:21,0:21:60:0,60,818 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:47,55:102:99:1750,0,1322 0/1:100,78:178:99:2590,0,2694 1/1:0,90:90:99:3594,269,0 0/0:28,0:28:63:0,63,945 1/1:2,90:92:99:3404,200,0 0/0:27,0:27:60:0,60,900 1/1:0,76:76:99:2887,228,0 0/1:56,45:101:99:1491,0,1647 0/0:27,0:27:66:0,66,990 0/1:66,61:127:99:2003,0,1939 0/1:61,49:110:99:1639,0,1860 0/1:42,33:75:99:1029,0,1254 1/1:1,63:64:99:2438,156,0 1/1:0,88:88:99:3454,265,0 0/0:30,0:30:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:31,0:31:61:0,61,1125 0/1:49,36:85:99:1041,0,1389 0/0:20,0:20:60:0,60,800 0/1:58,36:94:99:997,0,1742 0/1:138,106:244:99:3375,0,3975 0/1:85,49:134:99:1506,0,2337 0/0:21,0:21:60:0,60,843 0/0:26,0:26:60:0,60,900 1/1:1,54:55:99:2090,127,0 0/0:22,0:22:63:0,63,806 0/1:52,26:78:99:698,0,1336 1/1:0,100:100:99:3865,300,0 0/0:25,0:25:60:0,60,900 0/1:44,32:76:99:1042,0,1322 0/0:25,0:25:60:0,60,900 +20 10026348 . A G 7535.22 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.328;AN=200;InbreedingCoeff=-0.0052;AF=0.005172;GQ_STDDEV=70.7;FS=4.271;DP=23697;GQ_MEAN=78.63;VQSLOD=2.92;ClippingRankSum=0.362;BaseQRankSum=2.26;MLEAF=0.005172;MLEAC=9;MQ=59.24;QD=13.78;MQRankSum=0.325;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:72:0,72,1080 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:23,0:23:60:0,60,779 0/0:27,0:27:72:0,72,1080 0/0:21,0:21:60:0,60,722 0/0:24,0:24:63:0,63,894 0/0:21,0:21:60:0,60,900 0/0:24,0:24:72:0,72,914 0/1:25,18:43:99:463,0,687 0/0:34,0:34:93:0,93,1395 0/0:26,0:26:75:0,75,1125 0/0:25,0:25:69:0,69,868 0/1:43,56:99:99:1604,0,1081 0/0:32,0:32:71:0,71,1215 0/0:50,0:50:99:0,120,1800 0/0:31,0:31:60:0,60,1026 0/0:38,0:38:99:0,99,1485 0/0:45,0:45:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:43,0:43:99:0,120,1800 0/0:31,0:31:66:0,66,1117 0/0:24,0:24:66:0,66,990 0/0:21,0:21:63:0,63,723 0/0:31,0:31:87:0,87,1305 0/0:25,0:25:66:0,66,990 0/0:23,0:23:65:0,65,743 0/0:20,0:20:60:0,60,714 0/0:28,0:28:81:0,81,1044 0/0:29,0:29:87:0,87,975 0/0:25,0:25:69:0,69,1035 0/0:20,0:20:60:0,60,649 0/0:22,0:22:60:0,60,811 0/0:33,0:33:90:0,90,1350 0/0:20,0:20:60:0,60,722 0/0:39,0:39:99:0,111,1665 0/0:24,0:24:67:0,67,1035 0/0:27,0:27:75:0,75,1125 0/0:20,0:20:60:0,60,720 0/0:31,0:31:74:0,74,1153 0/0:25,0:25:69:0,69,1035 0/0:28,0:28:78:0,78,1170 0/0:34,0:34:96:0,96,1440 0/0:24,0:24:69:0,69,1020 0/0:26,0:26:75:0,75,1125 0/0:34,0:34:99:0,99,1485 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,717 0/0:23,0:23:69:0,69,762 0/0:33,0:33:99:0,99,1137 0/0:25,0:25:72:0,72,877 0/0:23,0:23:66:0,66,854 0/0:34,0:34:93:0,93,1395 0/0:22,0:22:63:0,63,902 0/0:30,0:30:84:0,84,1260 0/0:21,0:21:63:0,63,747 0/0:28,0:28:79:0,79,1007 0/0:34,0:34:99:0,99,1485 0/0:27,0:27:73:0,73,1065 0/0:31,0:31:93:0,93,1078 0/0:38,0:38:99:0,108,1620 0/0:21,0:21:63:0,63,765 0/0:22,0:22:63:0,63,945 0/0:43,0:43:99:0,120,1800 0/0:21,0:21:60:0,60,751 0/0:34,0:34:79:0,79,1218 0/0:21,0:21:60:0,60,695 0/0:29,0:29:87:0,87,961 0/0:21,0:21:60:0,60,900 0/0:24,0:24:72:0,72,856 0/0:21,0:21:60:0,60,751 0/0:20,0:20:60:0,60,659 0/0:21,0:21:60:0,60,739 0/0:20,0:20:60:0,60,753 0/0:23,0:23:69:0,69,757 0/0:28,0:28:66:0,66,990 0/0:20,0:20:60:0,60,739 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,644 0/0:34,0:34:87:0,87,1165 0/0:21,0:21:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:42,0:42:88:0,88,1409 0/0:39,0:39:99:0,102,1549 0/0:22,0:22:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:26,0:26:64:0,64,1073 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,721 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,660 0/0:23,0:23:69:0,69,798 0/0:22,0:22:60:0,60,900 0/0:29,0:29:69:0,69,963 +20 10026357 rs685723 T C 375167.00 PASS HWP=0.3757;AC=34;culprit=FS;MQ0=0;ReadPosRankSum=0.303;AN=200;InbreedingCoeff=0.0326;AF=0.23;GQ_STDDEV=433.13;FS=0.0;DP=36110;GQ_MEAN=323.69;POSITIVE_TRAIN_SITE;VQSLOD=6.98;ClippingRankSum=-0.152;BaseQRankSum=2.55;MLEAF=0.23;MLEAC=400;MQ=59.63;QD=17.07;DB;MQRankSum=0.153;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:72:0,72,1080 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:23,0:23:60:0,60,779 0/0:27,0:27:72:0,72,1080 0/0:21,0:21:60:0,60,722 0/0:24,0:24:63:0,63,894 0/0:21,0:21:60:0,60,900 0/0:24,0:24:72:0,72,914 0/0:23,0:23:60:0,60,900 0/0:34,0:34:93:0,93,1395 0/0:26,0:26:75:0,75,1125 0/1:24,35:59:99:1068,0,643 0/0:47,0:47:99:0,99,1485 0/1:50,49:99:99:1329,0,1367 0/0:50,0:50:99:0,120,1800 0/1:40,44:84:99:1266,0,1133 0/0:38,0:38:99:0,99,1485 0/1:58,51:109:99:1474,0,1678 0/1:38,42:80:99:1242,0,1022 0/0:43,0:43:99:0,120,1800 0/1:38,36:74:99:1124,0,1141 0/1:41,29:70:99:802,0,1157 0/0:21,0:21:63:0,63,723 0/1:38,27:65:99:837,0,958 0/0:25,0:25:66:0,66,990 0/0:23,0:23:65:0,65,743 0/0:20,0:20:60:0,60,714 0/0:28,0:28:81:0,81,1044 0/0:29,0:29:87:0,87,975 0/0:25,0:25:69:0,69,1035 0/1:39,52:91:99:1528,0,875 0/0:22,0:22:60:0,60,811 0/0:33,0:33:90:0,90,1350 1/1:0,49:49:99:1810,147,0 0/1:48,38:86:99:1161,0,1399 0/1:20,23:43:99:808,0,576 0/0:27,0:27:75:0,75,1125 0/0:20,0:20:60:0,60,720 0/0:31,0:31:74:0,74,1153 0/1:30,25:55:99:844,0,945 0/1:38,38:76:99:1149,0,1148 0/0:34,0:34:96:0,96,1440 0/0:24,0:24:69:0,69,1020 0/1:52,45:97:99:1520,0,1544 0/1:68,54:122:99:1779,0,1982 0/1:32,18:50:99:550,0,969 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,717 1/1:0,49:49:99:1825,147,0 0/1:67,42:109:99:1258,0,1834 0/1:40,29:69:99:890,0,1168 0/0:23,0:23:66:0,66,854 0/1:29,19:48:99:605,0,862 0/1:36,37:73:99:1156,0,1104 0/1:43,34:77:99:1169,0,1363 0/1:29,21:50:99:635,0,875 0/0:28,0:28:79:0,79,1007 0/0:34,0:34:99:0,99,1485 0/1:36,30:66:99:870,0,975 0/0:31,0:31:93:0,93,1078 0/1:47,22:69:99:612,0,1423 0/0:21,0:21:63:0,63,765 0/0:22,0:22:63:0,63,945 0/0:43,0:43:99:0,120,1800 0/0:21,0:21:60:0,60,751 0/0:34,0:34:79:0,79,1218 0/0:21,0:21:60:0,60,695 0/0:29,0:29:87:0,87,961 0/0:21,0:21:60:0,60,900 0/0:24,0:24:72:0,72,856 0/1:42,18:60:99:490,0,1242 0/1:31,39:70:99:1239,0,754 0/0:21,0:21:60:0,60,739 0/0:20,0:20:60:0,60,753 0/1:32,25:57:99:726,0,972 0/0:28,0:28:66:0,66,990 0/1:18,22:40:99:775,0,524 0/1:20,15:35:99:441,0,563 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,644 0/0:34,0:34:87:0,87,1165 0/0:21,0:21:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:42,0:42:88:0,88,1409 0/1:56,52:108:99:1864,0,1716 0/0:22,0:22:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:26,0:26:64:0,64,1073 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,721 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,660 0/0:23,0:23:69:0,69,798 0/0:22,0:22:60:0,60,900 0/0:29,0:29:69:0,69,963 +20 10030188 rs652633 T A 454459.00 PASS HWP=0.564;AC=34;culprit=FS;MQ0=0;ReadPosRankSum=0.466;AN=200;InbreedingCoeff=0.0221;AF=0.219;GQ_STDDEV=536.87;FS=0.536;DP=44099;GQ_MEAN=408.72;POSITIVE_TRAIN_SITE;VQSLOD=5.39;ClippingRankSum=-0.242;BaseQRankSum=1.2;MLEAF=0.219;MLEAC=381;MQ=59.68;QD=17.01;DB;MQRankSum=0.147;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:35,0:35:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:26,0:26:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:66:0,66,990 0/1:25,27:52:99:798,0,787 0/0:29,0:29:75:0,75,1125 0/1:27,26:53:99:797,0,808 0/0:73,0:73:99:0,120,1800 0/1:30,39:69:99:1193,0,818 0/0:30,0:30:60:0,60,900 0/1:52,40:92:99:1178,0,1555 0/1:42,45:87:99:1311,0,1254 0/0:26,0:26:60:0,60,900 0/1:50,49:99:99:1583,0,1453 0/1:61,52:113:99:1624,0,1917 0/0:25,0:25:60:0,60,900 0/1:53,68:121:99:2090,0,1537 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:51,0:51:99:0,120,1800 0/0:37,0:37:79:0,79,1350 0/0:41,0:41:81:0,81,1215 0/0:34,0:34:78:0,78,1170 0/1:35,43:78:99:1184,0,973 0/0:33,0:33:60:0,60,900 0/0:27,0:27:66:0,66,990 1/1:0,91:91:99:3470,274,0 0/1:69,66:135:99:2091,0,2091 0/1:52,55:107:99:1696,0,1664 0/0:27,0:27:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:29,0:29:60:0,60,900 0/1:71,85:156:99:2780,0,2147 0/1:53,66:119:99:2196,0,1587 0/0:27,0:27:66:0,66,990 0/0:32,0:32:74:0,74,1125 0/1:46,33:79:99:981,0,1453 0/1:53,51:104:99:1679,0,1643 0/1:73,60:133:99:1894,0,2249 0/0:35,0:35:60:0,60,900 0/0:22,0:22:60:0,60,900 1/1:0,58:58:99:2147,174,0 0/1:40,34:74:99:1076,0,1111 0/1:64,53:117:99:1550,0,1858 0/0:30,0:30:72:0,72,1080 0/1:90,71:161:99:2248,0,2783 0/1:73,76:149:99:2375,0,2208 0/1:55,45:100:99:1364,0,1739 0/1:47,49:96:99:1539,0,1381 0/0:35,0:35:68:0,68,1035 0/0:38,0:38:77:0,77,1376 0/1:66,51:117:99:1630,0,1998 0/0:27,0:27:66:0,66,990 0/1:36,41:77:99:1259,0,1126 0/0:28,0:28:69:0,69,1035 0/0:28,0:28:67:0,67,1190 0/0:33,0:33:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:60:0,60,900 0/1:17,16:33:99:502,0,553 0/1:37,21:58:99:593,0,1130 0/0:30,0:30:60:0,60,900 0/0:42,0:42:96:0,96,1440 0/1:31,36:67:99:1188,0,857 0/0:28,0:28:63:0,63,945 0/1:19,28:47:99:925,0,583 0/1:18,15:33:99:465,0,562 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 0/1:93,64:157:99:1879,0,2800 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:36,0:36:85:0,85,1305 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:33,0:33:80:0,80,1305 0/0:24,0:24:60:0,60,900 0/0:28,0:28:75:0,75,1125 +20 10030452 rs524625 G A 430836.00 PASS HWP=0.4003;AC=30;culprit=FS;MQ0=0;ReadPosRankSum=0.443;AN=200;InbreedingCoeff=0.0312;AF=0.216;GQ_STDDEV=559.99;FS=0.532;DP=43005;GQ_MEAN=402.05;POSITIVE_TRAIN_SITE;VQSLOD=5.67;ClippingRankSum=-0.265;BaseQRankSum=-3.232;MLEAF=0.216;MLEAC=375;MQ=59.65;QD=16.22;DB;MQRankSum=0.261;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:35,0:35:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:26,0:26:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:66:0,66,990 0/1:41,26:67:99:755,0,1276 0/0:29,0:29:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/0:73,0:73:99:0,120,1800 0/1:53,33:86:99:969,0,1631 0/0:30,0:30:60:0,60,900 0/1:45,51:96:99:1459,0,1305 0/0:30,0:30:66:0,66,990 0/0:26,0:26:60:0,60,900 0/1:70,69:139:99:2068,0,2149 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/1:65,62:127:99:1739,0,2115 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:51,0:51:99:0,120,1800 0/0:37,0:37:79:0,79,1350 0/0:41,0:41:81:0,81,1215 0/0:34,0:34:78:0,78,1170 0/1:16,28:44:99:791,0,508 0/0:33,0:33:60:0,60,900 0/0:27,0:27:66:0,66,990 1/1:0,100:100:99:3609,300,0 0/1:83,67:150:99:2025,0,2535 0/1:45,47:92:99:1441,0,1393 0/0:27,0:27:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:29,0:29:60:0,60,900 0/1:60,81:141:99:2460,0,1816 0/1:71,67:138:99:2045,0,2242 0/0:27,0:27:66:0,66,990 0/0:32,0:32:74:0,74,1125 0/1:53,63:116:99:1965,0,1762 0/1:64,58:122:99:1736,0,2117 0/1:64,82:146:99:2572,0,2015 0/0:35,0:35:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:44,37:81:99:1119,0,1409 0/1:62,56:118:99:1615,0,2034 0/1:77,82:159:99:2252,0,2282 0/0:30,0:30:72:0,72,1080 0/1:70,58:128:99:1827,0,2324 0/1:72,83:155:99:2529,0,2267 0/1:57,43:100:99:1281,0,1987 0/1:61,75:136:99:2333,0,1926 0/0:35,0:35:68:0,68,1035 0/0:38,0:38:77:0,77,1376 0/1:66,66:132:99:1964,0,2009 0/0:27,0:27:66:0,66,990 0/1:37,38:75:99:1124,0,1165 0/0:27,0:27:63:0,63,945 0/0:28,0:28:67:0,67,1190 0/0:33,0:33:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:60:0,60,900 0/1:22,31:53:99:904,0,697 0/1:44,32:76:99:916,0,1402 0/0:30,0:30:60:0,60,900 0/0:27,0:27:63:0,63,945 0/1:42,29:71:99:809,0,1434 0/0:28,0:28:63:0,63,945 0/1:26,30:56:99:867,0,891 0/1:40,34:74:99:980,0,1247 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 0/1:72,82:154:99:2457,0,2319 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:36,0:36:85:0,85,1305 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:33,0:33:80:0,80,1305 0/0:30,0:30:63:0,63,945 0/0:28,0:28:75:0,75,1125 +20 10030508 rs118040899 T C 9277.93 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.696;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=113.22;FS=0.528;DP=26086;GQ_MEAN=73.21;POSITIVE_TRAIN_SITE;VQSLOD=4.35;ClippingRankSum=-0.931;BaseQRankSum=2.92;MLEAF=0.002874;MLEAC=5;MQ=59.65;QD=18.19;DB;MQRankSum=0.148;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:35,0:35:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:26,0:26:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:33,0:33:60:0,60,1112 0/0:29,0:29:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/0:73,0:73:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:31,0:31:65:0,65,1070 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:51,0:51:99:0,120,1800 0/0:37,0:37:79:0,79,1350 0/0:41,0:41:81:0,81,1215 0/0:34,0:34:78:0,78,1170 0/0:38,0:38:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:27,0:27:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:32,0:32:70:0,70,1215 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:66:0,66,990 0/0:32,0:32:74:0,74,1125 0/0:29,0:29:81:0,81,1215 0/0:31,0:31:61:0,61,1035 0/0:35,0:35:81:0,81,1215 0/0:35,0:35:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:35,0:35:67:0,67,1225 0/0:30,0:30:66:0,66,990 0/0:30,0:30:72:0,72,1080 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:69:0,69,1035 0/0:33,0:33:78:0,78,1170 0/0:27,0:27:63:0,63,945 0/0:35,0:35:68:0,68,1035 0/0:38,0:38:77:0,77,1376 0/0:26,0:26:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:33,0:33:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:28,0:28:67:0,67,1190 0/0:33,0:33:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:28,0:28:62:0,62,990 0/0:27,0:27:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:34,0:34:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/0:22,0:22:60:0,60,798 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:35,0:35:78:0,78,1170 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,945 0/1:26,46:72:99:1682,0,797 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:33,0:33:80:0,80,1305 0/0:30,0:30:63:0,63,945 0/0:28,0:28:75:0,75,1125 +20 10030573 rs139192723 G A 7199.93 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.624;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=102.54;FS=0.544;DP=25972;GQ_MEAN=72.55;VQSLOD=2.74;ClippingRankSum=-0.072;BaseQRankSum=1.93;MLEAF=0.002874;MLEAC=5;MQ=60.0;QD=11.82;DB;MQRankSum=-0.673;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:35,0:35:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:26,0:26:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:33,0:33:60:0,60,1112 0/0:29,0:29:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/1:89,53:142:99:1500,0,2540 0/0:25,0:25:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:31,0:31:65:0,65,1070 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:60,60:120:99:1635,0,1658 0/0:37,0:37:79:0,79,1350 0/0:41,0:41:81:0,81,1215 0/0:34,0:34:78:0,78,1170 0/0:38,0:38:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:27,0:27:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:32,0:32:70:0,70,1215 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:66:0,66,990 0/0:32,0:32:74:0,74,1125 0/0:29,0:29:81:0,81,1215 0/0:31,0:31:61:0,61,1035 0/0:35,0:35:81:0,81,1215 0/0:35,0:35:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:35,0:35:67:0,67,1225 0/0:30,0:30:66:0,66,990 0/0:30,0:30:72:0,72,1080 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:69:0,69,1035 0/0:33,0:33:78:0,78,1170 0/0:27,0:27:63:0,63,945 0/0:35,0:35:68:0,68,1035 0/0:38,0:38:77:0,77,1376 0/0:26,0:26:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:33,0:33:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:28,0:28:67:0,67,1190 0/0:33,0:33:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:28,0:28:62:0,62,990 0/0:27,0:27:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:34,0:34:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/0:22,0:22:60:0,60,798 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:35,0:35:78:0,78,1170 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:33,0:33:80:0,80,1305 0/0:30,0:30:63:0,63,945 0/0:28,0:28:75:0,75,1125 +20 10032413 rs683145 T G 335656.00 PASS HWP=0.5513;AC=34;culprit=MQ;MQ0=0;ReadPosRankSum=0.291;AN=200;InbreedingCoeff=0.0227;AF=0.221;GQ_STDDEV=406.47;FS=0.0;DP=31987;GQ_MEAN=299.33;POSITIVE_TRAIN_SITE;VQSLOD=6.61;ClippingRankSum=-0.116;BaseQRankSum=0.5;MLEAF=0.221;MLEAC=385;MQ=60.0;QD=17.23;DB;MQRankSum=0.165;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:21,0:21:60:0,60,849 0/0:23,0:23:60:0,60,821 0/0:20,0:20:60:0,60,728 0/0:22,0:22:60:0,60,791 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:22,0:22:63:0,63,893 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,869 0/0:22,0:22:60:0,60,812 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,728 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,880 0/0:23,0:23:60:0,60,900 0/0:27,0:27:63:0,63,945 0/1:35,29:64:99:856,0,1030 0/0:20,0:20:60:0,60,763 0/1:27,14:41:99:407,0,812 0/0:27,0:27:63:0,63,945 0/1:31,36:67:99:1041,0,917 0/0:32,0:32:64:0,64,1164 0/1:32,34:66:99:1064,0,990 0/1:50,67:117:99:2129,0,1532 0/0:24,0:24:69:0,69,1032 0/1:22,37:59:99:1165,0,691 0/1:40,36:76:99:960,0,1230 0/0:26,0:26:63:0,63,945 0/1:31,22:53:99:628,0,929 0/0:27,0:27:66:0,66,857 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,806 0/0:26,0:26:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:29,0:29:63:0,63,945 0/1:26,24:50:99:703,0,659 0/0:21,0:21:60:0,60,900 0/0:28,0:28:60:0,60,900 1/1:0,64:64:99:2249,192,0 0/1:34,30:64:99:817,0,1090 0/1:17,20:37:99:609,0,495 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:28,0:28:60:0,60,900 0/1:32,42:74:99:1284,0,875 0/1:34,37:71:99:1148,0,1039 0/0:21,0:21:60:0,60,875 0/0:25,0:25:60:0,60,900 0/1:48,53:101:99:1852,0,1618 0/1:59,51:110:99:1589,0,1862 0/1:19,28:47:99:822,0,609 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,900 1/1:0,87:87:99:3147,262,0 0/1:47,55:102:99:1752,0,1479 0/1:43,23:66:99:612,0,1358 0/0:26,0:26:60:0,60,900 0/1:36,29:65:99:819,0,1193 0/1:34,35:69:99:1097,0,1033 0/1:47,51:98:99:1767,0,1550 0/1:30,33:63:99:1021,0,982 0/0:25,0:25:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/1:26,21:47:99:634,0,837 0/0:22,0:22:60:0,60,900 0/1:37,48:85:99:1484,0,1067 0/0:20,0:20:60:0,60,738 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,838 0/0:31,0:31:60:0,60,900 0/0:23,0:23:60:0,60,849 0/0:24,0:24:66:0,66,990 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,900 0/1:20,28:48:99:965,0,588 0/1:28,38:66:99:1298,0,908 0/0:22,0:22:60:0,60,863 0/0:22,0:22:60:0,60,861 0/1:30,32:62:99:1068,0,964 0/0:25,0:25:60:0,60,900 0/1:12,16:28:99:575,0,403 0/1:15,25:40:99:825,0,473 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,720 0/0:23,0:23:60:0,60,900 0/1:54,43:97:99:1347,0,1822 0/0:21,0:21:60:0,60,842 0/0:23,0:23:63:0,63,945 0/0:20,0:20:60:0,60,743 0/0:22,0:22:60:0,60,793 0/0:20,0:20:60:0,60,703 0/0:20,0:20:60:0,60,705 0/0:22,0:22:63:0,63,798 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,734 0/0:22,0:22:66:0,66,857 +20 10036107 . T G 1942.46 VQSRTrancheSNP99.95to100.00 HWP=0.8286;AC=13;culprit=FS;MQ0=0;ReadPosRankSum=0.106;AN=200;InbreedingCoeff=-0.082;AF=0.032;GQ_STDDEV=31.81;FS=124.658;DP=20271;GQ_MEAN=48.41;VQSLOD=-142.4;ClippingRankSum=1.6;BaseQRankSum=-3.085;MLEAF=0.034;MLEAC=60;MQ=58.55;QD=1.52;MQRankSum=-0.167;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:66:0,66,990 0/0:16,0:16:39:0,39,585 0/0:23,0:23:60:0,60,792 0/0:25,0:25:66:0,66,990 0/0:24,0:24:66:0,66,946 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,973 0/0:21,0:21:60:0,60,723 0/0:21,0:21:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:29,0:29:63:0,63,1125 0/0:26,0:26:60:0,60,900 0/0:23,0:23:63:0,63,874 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,932 0/0:32,0:32:94:0,94,1119 0/0:24,0:24:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:20,0:20:60:0,60,709 0/0:23,0:23:63:0,63,945 0/0:33,0:33:72:0,72,1215 0/0:24,0:24:67:0,67,835 0/0:18,0:18:51:0,51,765 0/0:17,0:17:0:0,0,448 0/0:12,0:12:24:0,24,360 0/0:26,0:26:0:0,0,548 0/0:13,0:13:0:0,0,275 0/0:13,0:13:0:0,0,352 0/0:36,0:36:96:0,96,1485 0/0:29,0:29:67:0,67,864 0/0:28,0:28:75:0,75,1046 0/0:31,0:31:84:0,84,1062 0/0:17,0:17:0:0,0,288 0/0:28,0:28:49:0,49,848 0/0:26,0:26:60:0,60,837 0/0:24,0:24:60:0,60,900 0/0:17,0:17:42:0,42,630 0/0:23,0:23:63:0,63,945 0/0:11,0:11:21:0,21,343 0/1:15,7:22:99:105,0,388 0/1:16,8:24:8:8,0,458 0/0:18,0:18:0:0,0,336 0/0:14,0:14:0:0,0,356 0/0:19,0:19:0:0,0,205 0/0:16,0:16:0:0,0,347 0/0:18,0:18:0:0,0,203 0/1:16,11:27:41:41,0,465 0/1:13,9:22:60:60,0,345 0/0:22,0:22:0:0,0,454 0/1:16,9:25:37:37,0,447 0/0:14,0:14:0:0,0,366 0/0:11,0:11:0:0,0,195 0/0:15,0:15:0:0,0,186 0/0:20,0:20:18:0,18,540 0/0:18,0:18:0:0,0,471 0/0:9,0:9:14:0,14,260 0/0:27,0:27:0:0,0,537 0/0:20,0:20:0:0,0,399 0/1:12,14:26:99:213,0,364 0/0:17,6:23:9:0,9,538 0/1:9,10:19:56:56,0,230 0/0:11,0:11:0:0,0,69 0/0:20,0:20:16:0,16,512 0/0:12,0:12:0:0,0,263 0/0:17,0:17:25:0,25,450 0/0:20,0:20:48:0,48,720 0/0:11,0:11:0:0,0,252 0/0:8,0:8:0:0,0,105 0/1:20,12:32:38:38,0,593 0/0:13,0:13:0:0,0,228 0/0:18,0:18:22:0,22,514 0/0:8,0:8:21:0,21,283 0/0:26,0:26:0:0,0,519 0/1:10,5:15:55:55,0,303 0/0:7,0:7:0:0,0,152 0/0:9,0:9:15:0,15,289 0/1:9,7:16:22:22,0,253 0/0:13,0:13:21:0,21,422 0/1:14,7:21:19:19,0,440 0/1:5,5:10:20:20,0,136 0/0:6,0:6:0:0,0,148 0/0:10,0:10:0:0,0,222 0/0:7,0:7:0:0,0,111 0/0:11,0:11:4:0,4,293 0/0:16,0:16:6:0,6,423 0/1:16,8:24:29:29,0,413 0/0:27,0:27:63:0,63,873 0/0:24,0:24:66:0,66,990 0/0:36,0:36:76:0,76,1170 0/0:17,0:17:25:0,25,422 0/0:21,0:21:60:0,60,768 0/0:17,0:17:45:0,45,577 0/0:8,0:8:0:0,0,204 0/0:7,0:7:21:0,21,250 0/0:21,0:21:63:0,63,702 0/0:24,0:24:60:0,60,900 0/0:11,0:11:30:0,30,397 0/0:6,0:6:0:0,0,114 0/0:11,0:11:0:0,0,260 0/0:10,0:10:0:0,0,217 +20 10036141 . C T 1979.21 VQSRTrancheSNP99.80to99.90 NEGATIVE_TRAIN_SITE;HWP=1.0;AC=8;culprit=FS;MQ0=0;ReadPosRankSum=-2.199;AN=200;InbreedingCoeff=-0.0576;AF=0.024;GQ_STDDEV=30.89;FS=26.106;DP=23701;GQ_MEAN=51.9;VQSLOD=-10.13;ClippingRankSum=1.91;BaseQRankSum=-2.387;MLEAF=0.024;MLEAC=41;MQ=59.3;QD=1.27;MQRankSum=-0.13;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:81:0,81,1215 0/0:16,0:16:39:0,39,585 0/0:27,0:27:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:24,0:24:66:0,66,946 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,973 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:29,0:29:63:0,63,1125 0/0:26,0:26:60:0,60,900 0/0:25,0:25:72:0,72,1080 0/0:23,0:23:60:0,60,872 0/0:24,0:24:63:0,63,932 0/0:32,0:32:94:0,94,1119 0/0:24,0:24:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:20,0:20:60:0,60,709 0/0:23,0:23:63:0,63,945 0/0:33,0:33:72:0,72,1215 0/0:24,0:24:67:0,67,835 0/0:23,0:23:60:0,60,812 0/0:23,0:23:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:44,0:44:0:0,0,1174 0/0:22,0:22:49:0,49,641 0/0:26,0:26:12:0,12,719 0/0:36,0:36:96:0,96,1485 0/0:29,0:29:67:0,67,864 0/0:28,0:28:75:0,75,1046 0/0:31,0:31:84:0,84,1062 0/0:37,0:37:59:0,59,1127 0/0:42,0:42:10:0,10,1319 0/0:26,0:26:60:0,60,837 0/0:24,0:24:60:0,60,900 0/0:22,0:22:63:0,63,836 0/0:23,0:23:63:0,63,945 0/0:32,0:32:57:0,57,1023 0/0:29,0:29:0:0,0,703 0/1:16,6:22:48:48,0,445 0/0:23,0:23:31:0,31,657 0/0:32,0:32:33:0,33,945 0/0:25,5:30:39:0,39,740 0/0:39,0:39:10:0,10,1071 0/0:37,0:37:34:0,34,1022 0/0:30,0:30:10:0,10,814 0/0:32,5:37:2:0,2,848 0/1:21,5:26:55:55,0,628 0/1:28,6:34:71:71,0,853 0/0:33,0:33:4:0,4,882 0/0:22,0:22:0:0,0,568 0/0:14,0:14:23:0,23,495 0/0:19,0:19:0:0,0,489 0/0:28,0:28:0:0,0,743 0/0:23,0:23:16:0,16,558 0/0:32,0:32:50:0,50,938 0/0:23,0:23:63:0,63,796 0/0:26,0:26:0:0,0,626 0/1:31,8:39:42:42,0,979 0/1:24,5:29:38:38,0,575 0/0:22,5:27:17:0,17,648 0/0:39,0:39:30:0,30,1099 0/0:26,0:26:18:0,18,796 0/0:32,0:32:0:0,0,816 0/0:29,0:29:75:0,75,1125 0/0:11,0:11:28:0,28,352 0/0:12,0:12:0:0,0,309 0/1:23,14:37:99:168,0,712 0/0:17,0:17:0:0,0,376 0/0:30,0:30:52:0,52,905 0/0:19,0:19:16:0,16,597 0/0:34,0:34:0:0,0,890 0/0:22,0:22:35:0,35,681 0/0:19,0:19:0:0,0,491 0/0:10,0:10:6:0,6,341 0/0:22,0:22:0:0,0,430 0/0:23,0:23:55:0,55,681 0/1:22,7:29:97:97,0,543 0/0:13,0:13:32:0,32,422 0/0:5,0:5:12:0,12,180 0/0:12,0:12:0:0,0,280 0/0:7,0:7:0:0,0,91 0/0:20,0:20:0:0,0,476 0/0:23,0:23:22:0,22,706 0/0:34,0:34:33:0,33,1040 0/0:27,0:27:63:0,63,873 0/0:24,0:24:66:0,66,990 0/0:36,0:36:76:0,76,1170 0/1:27,5:32:3:3,0,768 0/0:21,0:21:60:0,60,768 0/0:22,0:22:49:0,49,673 0/0:19,0:19:18:0,18,504 0/0:17,0:17:0:0,0,388 0/0:21,0:21:63:0,63,702 0/0:24,0:24:60:0,60,900 0/0:18,0:18:0:0,0,468 0/0:17,0:17:0:0,0,506 0/0:14,0:14:0:0,0,290 0/0:22,0:22:20:0,20,708 +20 10036202 rs6087119 G A 68876.90 PASS HWP=0.8653;AC=12;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.04;AN=200;InbreedingCoeff=-0.0229;AF=0.047;GQ_STDDEV=214.94;FS=0.0;DP=28184;GQ_MEAN=131.93;POSITIVE_TRAIN_SITE;VQSLOD=5.53;ClippingRankSum=-0.489;BaseQRankSum=1.87;MLEAF=0.047;MLEAC=81;MQ=59.67;QD=15.16;DB;MQRankSum=0.073;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:81:0,81,1215 0/0:22,0:22:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:24,0:24:66:0,66,946 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,973 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:29,0:29:63:0,63,1125 0/0:26,0:26:60:0,60,900 0/0:25,0:25:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:24,0:24:63:0,63,932 0/0:32,0:32:94:0,94,1119 0/1:24,22:46:99:659,0,615 0/0:27,0:27:63:0,63,945 0/0:20,0:20:60:0,60,709 0/1:31,33:64:99:1073,0,882 0/0:33,0:33:72:0,72,1215 0/0:24,0:24:67:0,67,835 0/0:23,0:23:60:0,60,812 0/0:23,0:23:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:43,0:43:75:0,75,1291 0/0:25,0:25:66:0,66,731 0/0:27,0:27:65:0,65,910 0/0:36,0:36:96:0,96,1485 0/0:29,0:29:67:0,67,864 0/0:28,0:28:75:0,75,1046 0/1:30,24:54:99:760,0,842 0/0:38,0:38:69:0,69,1355 0/0:42,0:42:90:0,90,1253 0/0:26,0:26:60:0,60,837 0/1:17,18:35:99:559,0,452 0/0:22,0:22:63:0,63,836 0/0:23,0:23:63:0,63,945 0/0:32,0:32:90:0,90,1178 0/0:29,0:29:63:0,63,896 0/0:22,0:22:60:0,60,900 0/0:26,0:26:68:0,68,967 0/0:31,0:31:66:0,66,990 0/0:33,0:33:65:0,65,951 0/1:38,27:65:99:841,0,1109 0/0:64,0:64:99:0,120,1800 0/0:31,0:31:68:0,68,961 0/0:40,0:40:99:0,99,1755 0/0:28,0:28:70:0,70,1152 0/0:33,0:33:70:0,70,1108 0/0:33,0:33:93:0,93,1366 0/0:21,0:21:60:0,60,660 0/0:22,0:22:60:0,60,654 0/0:28,0:28:63:0,63,945 0/0:27,0:27:69:0,69,917 0/0:27,0:27:60:0,60,900 0/1:34,35:69:99:1132,0,1007 0/1:37,39:76:99:1242,0,1017 0/0:22,0:22:63:0,63,826 0/1:39,45:84:99:1517,0,1231 0/0:31,0:31:93:0,93,1111 0/0:27,0:27:66:0,66,990 0/0:62,0:62:99:0,120,1800 0/1:30,27:57:99:805,0,860 0/0:29,0:29:84:0,84,870 0/0:29,0:29:75:0,75,1125 0/0:21,0:21:60:0,60,796 0/0:23,0:23:63:0,63,945 0/0:57,0:57:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:31,0:31:80:0,80,1148 0/1:26,22:48:99:660,0,810 0/0:37,0:37:69:0,69,1125 0/1:31,21:52:99:605,0,909 0/0:29,0:29:63:0,63,945 0/1:13,14:27:99:436,0,372 0/0:34,0:34:78:0,78,1170 0/0:36,0:36:77:0,77,1215 0/0:30,0:30:60:0,60,900 0/0:24,0:24:66:0,66,738 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,897 0/0:26,0:26:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:34,0:34:75:0,75,1096 0/0:27,0:27:63:0,63,873 0/0:24,0:24:66:0,66,990 0/0:36,0:36:76:0,76,1170 0/0:34,0:34:93:0,93,1176 0/0:21,0:21:60:0,60,768 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,785 0/0:26,0:26:63:0,63,945 0/0:21,0:21:63:0,63,702 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:62:0,62,1010 0/0:21,0:21:60:0,60,696 0/0:24,0:24:63:0,63,852 +20 10256252 rs362585 G T 35632.00 PASS HWP=0.0097;AC=18;culprit=MQ;MQ0=0;ReadPosRankSum=0.283;AN=196;InbreedingCoeff=0.0235;AF=0.118;GQ_STDDEV=56.81;FS=0.0;DP=8219;GQ_MEAN=42.86;POSITIVE_TRAIN_SITE;VQSLOD=6.81;ClippingRankSum=0.194;BaseQRankSum=-1.276;MLEAF=0.125;MLEAC=217;MQ=60.0;QD=15.89;DB;MQRankSum=0.301;CCC=1730;NCC=5 GT:AD:DP:GQ:PL 0/1:2,5:7:60:166,0,60 0/0:6,0:6:15:0,15,219 0/1:9,7:16:99:203,0,285 0/0:10,0:10:27:0,27,405 0/0:8,0:8:21:0,21,290 0/0:9,0:9:22:0,22,322 0/1:10,4:14:99:116,0,369 0/0:3,0:3:6:0,6,90 0/1:4,3:7:90:90,0,109 0/0:6,0:6:18:0,18,235 0/0:4,0:4:9:0,9,135 0/0:4,0:4:12:0,12,147 0/1:2,7:9:48:234,0,48 0/0:7,0:7:21:0,21,273 0/0:3,0:3:6:0,6,90 0/1:4,3:7:95:95,0,109 0/1:2,3:5:64:92,0,64 0/0:5,0:5:12:0,12,180 0/0:5,0:5:6:0,6,90 0/0:10,0:10:21:0,21,315 0/0:9,0:9:23:0,23,328 0/0:8,0:8:21:0,21,315 0/0:5,0:5:0:0,0,121 0/0:12,0:12:21:0,21,315 0/0:10,0:10:27:0,27,405 0/0:8,0:8:21:0,21,283 0/0:15,0:15:33:0,33,540 0/0:11,0:11:27:0,27,386 0/1:13,5:18:99:129,0,471 0/0:14,0:14:36:0,36,508 0/1:12,6:18:99:138,0,425 0/0:11,0:11:24:0,24,360 0/0:11,0:11:30:0,30,450 0/0:15,0:15:39:0,39,585 0/0:10,0:10:24:0,24,360 0/0:7,0:7:0:0,0,182 0/0:6,0:6:12:0,12,180 0/0:5,0:5:12:0,12,180 0/0:4,0:4:9:0,9,135 0/0:7,0:7:21:0,21,256 0/0:8,0:8:21:0,21,315 0/0:13,0:13:22:0,22,405 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,249 0/0:9,0:9:24:0,24,360 0/0:24,0:24:60:0,60,900 0/1:8,5:13:99:120,0,246 0/0:11,0:11:27:0,27,405 0/0:6,0:6:18:0,18,241 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,307 0/0:7,0:7:15:0,15,225 0/0:5,0:5:12:0,12,180 0/0:6,0:6:15:0,15,225 0/1:4,3:7:97:97,0,153 0/1:7,5:12:99:114,0,249 0/0:12,0:12:27:0,27,402 0/0:9,0:9:21:0,21,315 0/1:7,4:11:99:123,0,200 0/1:6,4:10:99:126,0,233 0/0:3,0:3:9:0,9,105 0/0:3,0:3:9:0,9,117 0/0:11,0:11:24:0,24,360 0/0:5,0:5:15:0,15,188 0/0:8,0:8:21:0,21,241 0/0:4,0:4:9:0,9,135 0/0:2,0:2:6:0,6,82 0/0:4,0:4:12:0,12,163 0/0:10,0:10:27:0,27,405 0/0:3,0:3:9:0,9,115 0/1:6,4:10:99:123,0,235 0/0:5,0:5:12:0,12,180 0/1:5,6:11:99:164,0,163 0/0:7,0:7:21:0,21,232 0/1:4,3:7:62:62,0,147 0/0:2,0:2:6:0,6,63 0/0:3,0:3:6:0,6,90 0/0:5,0:5:12:0,12,180 0/0:3,0:3:0:0,0,43 0/0:7,0:7:21:0,21,271 0/0:4,0:4:9:0,9,135 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,81 0/0:7,0:7:0:0,0,213 ./.:0,0:0:.:. 0/0:7,0:7:21:0,21,263 0/0:6,0:6:12:0,12,180 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,52 0/0:12,0:12:33:0,33,495 0/1:8,5:13:99:119,0,301 0/0:10,0:10:21:0,21,315 0/0:7,0:7:21:0,21,245 0/0:5,0:5:12:0,12,180 0/0:9,0:9:0:0,0,255 0/0:4,0:4:6:0,6,90 0/0:2,0:2:6:0,6,78 ./.:1,0:1:.:. 0/0:3,0:3:6:0,6,90 0/0:3,0:3:9:0,9,115 +20 10273694 . C CT 29059.60 VQSRTrancheINDEL97.00to99.00 HWP=0.0;AC=17;culprit=QD;MQ0=0;ReadPosRankSum=-0.05;AN=200;InbreedingCoeff=-0.036;AF=0.097;GQ_STDDEV=57.24;FS=2.279;DP=52078;GQ_MEAN=43.73;VQSLOD=0.137;ClippingRankSum=-0.251;BaseQRankSum=0.221;MLEAF=0.09;MLEAC=157;MQ=59.11;QD=1.45;MQRankSum=0.087;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:33,4:41:32:0,32,830 0/0:63,0:63:0:0,0,1271 0/0:27,4:34:1:0,1,613 0/0:32,0:40:79:0,79,791 0/0:36,3:46:56:0,56,885 0/0:26,4:34:4:0,4,635 0/0:63,0:63:0:0,0,1763 0/1:25,4:29:13:13,0,486 0/0:61,0:61:29:0,29,1872 0/0:50,0:50:23:0,23,1436 0/0:32,7:48:0:0,0,787 0/0:19,3:28:29:0,29,1315 0/1:29,7:42:41:41,0,655 0/0:46,0:46:0:0,0,1217 0/0:21,5:58:77:0,77,822 0/0:26,3:36:31:0,31,688 0/1:25,9:37:99:108,0,556 0/1:26,6:38:27:27,0,597 0/0:27,5:39:0:0,0,664 0/0:40,5:55:47:0,47,1048 0/0:56,0:56:10:0,10,1388 0/0:34,5:47:22:0,22,856 0/1:35,8:50:45:45,0,845 0/0:50,0:50:63:0,63,945 0/1:15,6:21:85:85,0,294 0/0:58,6:71:74:0,74,1415 0/0:60,0:66:99:0,178,1538 0/0:35,6:50:33:0,33,814 0/0:47,7:66:0:0,0,1147 0/0:22,6:34:0:0,0,527 0/0:48,0:48:0:0,0,1347 0/0:20,0:23:59:0,59,475 0/0:63,5:86:99:0,125,1727 0/0:60,9:86:35:0,35,1557 0/0:54,7:67:48:0,48,1323 0/0:18,0:18:5:0,5,514 0/0:9,0:22:27:0,27,230 0/0:25,3:40:31:0,31,674 0/0:55,0:65:99:0,165,1432 0/0:56,10:76:6:0,6,1339 0/0:42,5:55:67:0,67,1039 0/0:83,0:83:0:0,0,2245 0/1:37,6:47:15:15,0,834 0/0:85,0:85:54:0,54,2582 0/0:64,0:71:99:0,193,1686 0/0:108,0:108:58:0,58,3355 0/0:52,2:62:99:0,130,1394 0/0:66,5:83:99:0,146,1800 0/0:49,7:62:35:0,35,1156 0/0:49,3:59:98:0,98,1282 0/0:57,0:64:99:0,171,1557 0/0:48,5:61:81:0,81,1264 0/0:36,0:41:99:0,108,1022 0/1:34,9:51:72:72,0,804 0/0:44,5:59:28:0,28,1088 0/0:59,0:68:99:0,176,1594 0/0:50,4:66:99:0,102,1352 0/0:62,0:71:99:0,183,1733 0/0:45,6:61:48:0,48,1093 0/0:65,11:84:99:0,118,1711 0/0:54,4:64:99:0,105,1406 0/0:80,0:80:13:0,13,2219 0/0:65,7:94:99:0,103,1755 0/1:34,8:45:43:43,0,731 0/0:49,0:57:99:0,147,1304 0/1:30,4:44:76:76,0,712 0/0:38,0:38:32:0,32,1183 0/1:19,4:23:29:29,0,371 0/1:49,8:61:27:27,0,1134 0/0:28,3:38:52:0,52,758 0/0:71,5:82:99:0,117,1790 0/1:33,11:48:95:95,0,749 0/0:59,8:81:46:0,46,1486 0/0:60,0:60:8:0,8,1735 0/0:28,4:37:7:0,7,666 0/1:20,5:25:53:53,0,407 0/0:26,0:29:77:0,77,627 0/0:36,3:42:48:0,48,876 0/0:24,0:30:72:0,72,599 0/0:53,0:53:0:0,0,1483 0/0:23,0:30:69:0,69,582 0/0:46,0:46:11:0,11,1305 0/0:35,0:35:0:0,0,1084 0/0:62,0:62:20:0,20,1955 0/0:63,0:63:13:0,13,1878 0/0:44,4:56:78:0,78,1146 0/0:27,0:27:0:0,0,667 0/0:21,0:21:0:0,0,564 0/0:32,0:39:96:0,96,926 0/0:61,8:74:49:0,49,1489 0/0:13,0:13:6:0,6,407 0/1:22,4:26:21:21,0,458 0/0:63,0:63:0:0,0,1880 0/1:22,3:25:2:2,0,486 0/0:33,0:33:0:0,0,639 0/0:11,0:11:0:0,0,215 0/0:48,0:48:0:0,0,1403 0/0:31,2:33:49:0,49,713 0/1:14,5:24:59:59,0,342 0/0:37,0:42:99:0,110,920 +20 10273694 . CT C 29059.60 VQSRTrancheINDEL97.00to99.00 HWP=0.0;AC=37;culprit=QD;MQ0=0;ReadPosRankSum=-0.05;AN=200;InbreedingCoeff=-0.036;AF=0.187;GQ_STDDEV=57.24;FS=2.279;DP=52078;GQ_MEAN=43.73;VQSLOD=0.137;ClippingRankSum=-0.251;BaseQRankSum=0.221;MLEAF=0.183;MLEAC=319;MQ=59.11;QD=1.45;MQRankSum=0.087;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:33,4:41:43:0,43,947 0/0:63,0:63:0:0,0,1271 0/0:27,3:34:24:0,24,687 0/1:32,5:40:39:39,0,697 0/1:36,7:46:27:27,0,866 0/0:26,4:34:13:0,13,778 0/0:63,0:63:0:0,0,1763 0/0:25,0:29:74:0,74,573 0/0:61,0:61:29:0,29,1872 0/0:50,0:50:23:0,23,1436 0/1:32,9:48:28:28,0,931 0/1:19,6:28:72:72,0,428 0/0:29,6:42:0:0,0,800 0/0:46,0:46:0:0,0,1217 0/1:21,28:58:99:586,0,532 0/1:26,7:36:56:56,0,772 0/0:25,3:37:30:0,30,725 0/0:26,6:38:0:0,0,704 0/1:27,7:39:34:34,0,722 0/1:40,10:55:67:67,0,1156 0/0:56,0:56:10:0,10,1388 0/1:34,8:47:9:9,0,924 0/0:35,7:50:0:0,0,974 0/0:50,0:50:63:0,63,945 0/0:15,0:21:48:0,48,360 0/0:58,7:71:25:0,25,1431 0/0:60,6:66:57:0,57,1395 0/0:35,9:50:29:0,29,1440 0/1:47,10:66:29:29,0,1336 0/1:22,6:34:57:57,0,569 0/0:48,0:48:0:0,0,1347 0/1:20,3:23:14:14,0,404 0/1:63,15:86:82:82,0,1672 0/1:60,17:86:99:105,0,1708 0/0:54,6:67:49:0,49,1520 0/0:18,0:18:5:0,5,514 0/1:9,13:22:99:229,0,163 0/1:25,12:40:99:187,0,640 0/1:55,10:65:28:28,0,1234 0/1:56,10:76:4:4,0,1486 0/1:42,8:55:6:6,0,1108 0/0:83,0:83:0:0,0,2245 0/0:37,4:47:39:0,39,1005 0/0:85,0:85:54:0,54,2582 0/0:64,7:71:57:0,57,1527 0/0:108,0:108:58:0,58,3355 0/1:52,8:62:7:7,0,1403 0/1:66,12:83:33:33,0,1785 0/0:49,6:62:74:0,74,1295 0/0:49,7:59:38:0,38,1393 0/1:57,7:64:2:2,0,1361 0/0:48,8:61:42:0,42,1442 0/0:36,5:41:4:0,4,901 0/0:34,4:51:60:0,60,994 0/0:44,5:59:63:0,63,1308 0/1:59,9:68:24:24,0,1387 0/1:50,12:66:83:83,0,1336 0/1:62,9:71:12:12,0,1519 0/1:45,10:61:61:61,0,1180 0/1:65,2:84:56:56,0,1698 0/0:54,6:64:56:0,56,1493 0/0:80,0:80:13:0,13,2219 0/1:65,19:94:99:233,0,1732 0/0:34,3:45:74:0,74,1220 0/1:49,8:57:28:28,0,1130 0/0:30,2:44:30:0,30,863 0/0:38,0:38:32:0,32,1183 0/0:19,0:23:58:0,58,441 0/0:49,4:61:92:0,92,1342 0/1:28,7:38:75:75,0,689 0/0:71,6:82:99:0,135,1964 0/0:33,4:48:42:0,42,971 0/1:59,14:81:22:22,0,1576 0/0:60,0:60:8:0,8,1735 0/1:28,5:37:7:7,0,674 0/0:20,0:25:61:0,61,483 0/0:26,3:29:3:0,3,542 0/0:36,3:42:55:0,55,1013 0/1:24,6:30:72:72,0,507 0/0:53,0:53:0:0,0,1483 0/1:23,7:30:97:97,0,491 0/0:46,0:46:11:0,11,1305 0/0:35,0:35:0:0,0,1084 0/0:62,0:62:20:0,20,1955 0/0:63,0:63:13:0,13,1878 0/1:44,8:56:10:10,0,1312 0/0:27,0:27:0:0,0,667 0/0:21,0:21:0:0,0,564 0/1:32,7:39:55:55,0,807 0/0:61,5:74:88:0,88,1779 0/0:13,0:13:6:0,6,407 0/0:22,0:26:68:0,68,538 0/0:63,0:63:0:0,0,1880 0/0:22,0:25:67:0,67,562 0/0:33,0:33:0:0,0,639 0/0:11,0:11:0:0,0,215 0/0:48,0:48:0:0,0,1403 0/0:31,0:33:95:0,95,765 0/0:14,5:24:0:0,0,409 0/1:37,5:42:11:11,0,792 +20 10277621 rs362998 C T 163618.00 PASS HWP=0.477;AC=28;culprit=QD;MQ0=0;ReadPosRankSum=0.542;AN=200;InbreedingCoeff=0.0276;AF=0.132;GQ_STDDEV=280.23;FS=1.126;DP=32524;GQ_MEAN=204.85;POSITIVE_TRAIN_SITE;VQSLOD=5.7;ClippingRankSum=-0.272;BaseQRankSum=-0.692;MLEAF=0.132;MLEAC=230;MQ=59.68;QD=13.14;DB;MQRankSum=0.346;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:35,34:69:99:1040,0,994 0/0:31,0:31:60:0,60,900 0/1:31,19:50:99:503,0,900 0/0:26,0:26:63:0,63,945 0/0:25,0:25:61:0,61,945 0/0:26,0:26:60:0,60,900 0/1:34,26:60:99:768,0,922 0/0:25,0:25:60:0,60,900 0/1:31,23:54:99:673,0,873 0/0:29,0:29:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:44,27:71:99:748,0,1322 0/0:24,0:24:60:0,60,900 0/0:23,0:23:66:0,66,764 0/1:23,27:50:99:733,0,599 0/1:34,20:54:99:567,0,979 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:34,0:34:81:0,81,1215 0/1:24,18:42:99:534,0,740 0/0:41,0:41:78:0,78,1170 0/0:35,0:35:81:0,81,1215 0/0:29,0:29:63:0,63,945 0/0:35,0:35:72:0,72,1080 0/0:25,0:25:60:0,60,900 0/1:42,28:70:99:637,0,1262 0/0:27,0:27:66:0,66,990 0/1:26,35:61:99:976,0,663 0/0:23,0:23:60:0,60,900 0/0:49,0:49:99:0,102,1530 0/0:57,0:57:99:0,120,1800 0/0:44,0:44:93:0,93,1395 0/1:22,23:45:99:644,0,606 0/0:23,0:23:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:33,0:33:75:0,75,1125 0/0:30,0:30:64:0,64,976 0/0:27,0:27:60:0,60,900 0/0:22,0:22:63:0,63,911 0/0:36,0:36:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/0:37,0:37:84:0,84,1260 0/1:24,21:45:99:500,0,698 0/0:34,0:34:60:0,60,900 0/0:36,0:36:78:0,78,1170 0/0:29,0:29:63:0,63,945 0/0:33,0:33:81:0,81,1215 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/1:19,12:31:99:337,0,632 0/1:46,21:67:99:513,0,1536 0/1:23,17:40:99:435,0,655 0/0:37,0:37:81:0,81,1215 0/1:30,25:55:99:751,0,789 0/1:16,13:29:99:367,0,364 0/1:33,32:65:99:983,0,1061 0/0:24,0:24:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:53,0:53:99:0,120,1800 0/0:37,0:37:81:0,81,1260 0/0:31,0:31:69:0,69,1018 0/0:30,0:30:60:0,60,900 0/0:21,0:21:60:0,60,797 0/0:21,0:21:48:0,48,720 0/0:33,0:33:75:0,75,1125 0/0:30,0:30:69:0,69,1035 0/1:35,16:51:99:358,0,1189 0/0:28,0:28:69:0,69,1035 0/1:34,29:63:99:841,0,974 0/0:30,0:30:75:0,75,1125 0/1:13,19:32:99:571,0,379 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/1:19,16:35:99:454,0,604 0/0:24,0:24:60:0,60,900 0/1:17,13:30:99:365,0,509 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,831 0/1:23,14:37:99:381,0,789 0/0:31,0:31:64:0,64,1080 0/0:24,0:24:66:0,66,990 0/0:30,0:30:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/1:49,32:81:99:889,0,1592 0/1:63,46:109:99:1157,0,1723 0/0:29,0:29:66:0,66,990 0/0:25,0:25:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:29,0:29:66:0,66,990 0/1:35,26:61:99:655,0,950 0/0:33,0:33:60:0,60,900 0/1:26,20:46:99:577,0,868 0/0:26,0:26:61:0,61,945 0/0:29,0:29:60:0,60,900 +20 10280082 . A G 844.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=2.06;AN=200;InbreedingCoeff=-7.0E-4;AF=5.747E-4;GQ_STDDEV=33.93;FS=0.0;DP=28908;GQ_MEAN=73.58;VQSLOD=1.67;ClippingRankSum=-2.073;BaseQRankSum=3.06;MLEAF=5.747E-4;MLEAC=1;MQ=58.43;QD=15.08;MQRankSum=0.844;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:69:0,69,1035 0/0:15,0:15:39:0,39,527 0/0:23,0:23:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:34,0:34:75:0,75,1125 0/0:27,0:27:72:0,72,1080 0/0:35,0:35:90:0,90,1350 0/0:30,0:30:49:0,49,980 0/0:29,0:29:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:38,0:38:90:0,90,1395 0/0:27,0:27:60:0,60,900 0/0:24,0:24:48:0,48,720 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:13,0:13:24:0,24,360 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:64,0:64:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:46,0:46:99:0,111,1665 0/0:47,0:47:99:0,99,1485 0/0:42,0:42:99:0,108,1620 0/0:30,0:30:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:30,0:30:63:0,63,945 0/0:54,0:54:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:42,0:42:78:0,78,1485 0/0:31,0:31:78:0,78,1170 0/0:25,0:25:60:0,60,900 0/0:34,0:34:78:0,78,1170 0/0:46,0:46:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:29,0:29:72:0,72,1053 0/0:27,0:27:69:0,69,1035 0/0:39,0:39:84:0,84,1260 0/0:47,0:47:99:0,105,1575 0/0:47,0:47:99:0,112,1800 0/0:46,0:46:99:0,114,1710 0/0:65,0:65:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:32,0:32:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:33,0:33:65:0,65,990 0/0:30,0:30:60:0,60,900 0/0:68,0:68:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:31,0:31:75:0,75,1125 0/0:45,0:45:99:0,111,1665 0/0:66,0:66:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:35,0:35:90:0,90,1350 0/0:48,0:48:99:0,105,1575 0/0:28,0:28:60:0,60,900 0/0:14,0:14:36:0,36,540 0/0:10,0:10:21:0,21,315 0/0:42,0:42:86:0,86,1613 0/0:12,0:12:26:0,26,405 0/0:25,0:25:60:0,60,900 0/0:17,0:17:45:0,45,675 0/0:25,0:25:69:0,69,1035 0/0:15,0:15:29:0,29,495 0/0:30,0:30:65:0,65,990 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:57:0,57,855 0/0:13,0:13:33:0,33,495 0/0:27,0:27:60:0,60,900 0/0:12,0:12:27:0,27,405 0/0:23,0:23:60:0,60,900 0/0:20,0:20:45:0,45,675 0/0:28,0:28:60:0,60,900 0/0:24,0:24:51:0,51,765 0/0:48,0:48:99:0,102,1530 0/0:29,0:29:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:51,0:51:99:0,117,1755 0/1:28,28:56:99:895,0,708 0/0:57,0:57:99:0,120,1800 0/0:25,0:25:60:0,60,900 0/0:15,0:15:39:0,39,585 0/0:53,0:53:99:0,120,1800 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:11,0:11:30:0,30,403 0/0:32,0:32:75:0,75,1125 +20 10280083 rs363006 G A 131212.00 PASS HWP=0.3034;AC=22;culprit=MQ;MQ0=0;ReadPosRankSum=0.318;AN=200;InbreedingCoeff=0.0387;AF=0.136;GQ_STDDEV=229.51;FS=0.782;DP=28537;GQ_MEAN=167.76;POSITIVE_TRAIN_SITE;VQSLOD=5.68;ClippingRankSum=-0.039;BaseQRankSum=-2.762;MLEAF=0.136;MLEAC=236;MQ=60.0;QD=15.05;DB;MQRankSum=0.172;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:45:0,45,931 0/0:15,0:15:39:0,39,527 0/0:23,0:23:60:0,60,900 0/1:18,11:29:99:285,0,605 0/0:27,0:27:60:0,60,900 0/0:24,0:24:35:0,35,824 0/0:32,0:32:58:0,58,1172 0/0:27,0:27:72:0,72,1080 0/0:35,0:35:90:0,90,1350 0/1:12,16:28:99:489,0,352 0/0:29,0:29:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:38,0:38:90:0,90,1395 0/0:27,0:27:60:0,60,900 0/1:15,8:23:99:230,0,476 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:13,0:13:24:0,24,360 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:64,0:64:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:46,0:46:99:0,111,1665 0/0:47,0:47:99:0,99,1485 0/0:42,0:42:99:0,108,1620 0/0:30,0:30:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:30,0:30:63:0,63,945 0/0:54,0:54:99:0,120,1800 0/1:33,26:59:99:731,0,1144 0/0:42,0:42:78:0,78,1485 0/1:21,10:31:99:234,0,601 0/0:25,0:25:60:0,60,900 0/1:23,10:33:99:238,0,746 0/0:46,0:46:99:0,120,1800 0/1:37,37:74:99:1092,0,1147 0/0:29,0:29:72:0,72,1053 0/0:27,0:27:69:0,69,1035 0/0:39,0:39:84:0,84,1260 0/0:47,0:47:99:0,105,1575 0/0:47,0:47:99:0,112,1800 0/0:46,0:46:99:0,114,1710 0/1:33,31:64:99:956,0,980 0/0:57,0:57:99:0,120,1800 0/1:19,29:48:99:882,0,643 0/1:28,22:50:99:659,0,981 0/0:59,0:59:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:32,0:32:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:33,0:33:65:0,65,990 0/0:30,0:30:60:0,60,900 0/0:68,0:68:99:0,120,1800 0/1:40,48:88:99:1489,0,1296 0/0:54,0:54:99:0,120,1800 0/0:31,0:31:75:0,75,1125 0/1:20,25:45:99:783,0,607 0/1:28,34:62:99:1053,0,856 0/0:54,0:54:99:0,120,1800 0/0:35,0:35:90:0,90,1350 0/0:48,0:48:99:0,105,1575 0/0:28,0:28:60:0,60,900 0/0:14,0:14:36:0,36,540 0/0:10,0:10:21:0,21,315 0/0:42,0:42:86:0,86,1613 0/0:12,0:12:26:0,26,405 0/0:25,0:25:60:0,60,900 0/0:17,0:17:45:0,45,675 0/0:25,0:25:69:0,69,1035 0/0:15,0:15:29:0,29,495 0/0:30,0:30:65:0,65,990 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/1:13,10:23:99:258,0,471 0/0:13,0:13:33:0,33,495 0/0:27,0:27:60:0,60,900 0/0:12,0:12:27:0,27,405 0/1:12,11:23:99:323,0,387 0/1:10,9:19:99:251,0,326 0/0:28,0:28:60:0,60,900 0/1:14,11:25:99:322,0,478 0/1:22,24:46:99:686,0,758 0/0:29,0:29:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:51,0:51:99:0,117,1755 0/0:31,0:31:72:0,72,1080 0/1:28,28:56:99:738,0,789 0/0:25,0:25:60:0,60,900 0/0:15,0:15:39:0,39,585 0/1:25,25:50:99:699,0,739 0/1:17,17:34:99:477,0,497 0/0:26,0:26:63:0,63,945 0/1:13,17:30:99:527,0,438 0/0:11,0:11:30:0,30,403 0/0:32,0:32:75:0,75,1125 +20 10286773 rs79020892 C T 29598.30 PASS HWP=0.043;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.293;AN=200;InbreedingCoeff=0.1033;AF=0.027;GQ_STDDEV=124.14;FS=0.0;DP=23794;GQ_MEAN=92.04;POSITIVE_TRAIN_SITE;VQSLOD=5.59;ClippingRankSum=-0.099;BaseQRankSum=-2.631;MLEAF=0.027;MLEAC=47;MQ=60.0;QD=13.27;DB;MQRankSum=-0.068;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:75:0,75,1052 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,706 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:63:0,63,931 0/0:30,0:30:60:0,60,900 0/0:22,0:22:60:0,60,832 0/0:21,0:21:63:0,63,792 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:14,0:14:33:0,33,495 0/0:21,0:21:60:0,60,900 0/0:21,0:21:63:0,63,776 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,737 0/1:26,24:50:99:652,0,770 0/0:26,0:26:66:0,66,854 0/0:21,0:21:63:0,63,727 0/0:20,0:20:60:0,60,743 0/0:28,0:28:81:0,81,1215 0/0:42,0:42:99:0,114,1710 0/0:23,0:23:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:72:0,72,1080 0/0:27,0:27:66:0,66,990 0/0:26,0:26:63:0,63,945 0/1:32,38:70:99:1032,0,855 0/0:42,0:42:89:0,89,1730 0/0:46,0:46:94:0,94,1575 0/0:44,0:44:93:0,93,1395 0/0:32,0:32:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:35,0:35:84:0,84,1260 0/0:25,0:25:66:0,66,990 0/0:26,0:26:66:0,66,990 0/0:25,0:25:66:0,66,959 0/0:27,0:27:69:0,69,1035 0/0:24,0:24:66:0,66,990 0/0:26,0:26:69:0,69,1035 0/0:25,0:25:72:0,72,904 0/0:25,0:25:63:0,63,945 0/0:20,0:20:60:0,60,723 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,822 0/0:28,0:28:62:0,62,990 0/0:27,0:27:60:0,60,900 0/0:22,0:22:63:0,63,788 0/0:28,0:28:75:0,75,1125 0/0:25,0:25:66:0,66,985 0/0:32,0:32:84:0,84,1260 0/0:25,0:25:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:32,0:32:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:33,0:33:69:0,69,1035 0/0:25,0:25:63:0,63,932 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:24,0:24:63:0,63,909 0/0:29,0:29:84:0,84,1260 0/0:27,0:27:63:0,63,929 0/0:28,0:28:64:0,64,990 0/0:21,0:21:60:0,60,815 0/0:29,0:29:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,851 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,841 0/0:21,0:21:63:0,63,743 0/0:23,0:23:60:0,60,900 0/0:20,0:20:54:0,54,810 0/0:25,0:25:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,887 0/0:24,0:24:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:36,0:36:92:0,92,1262 0/0:22,0:22:60:0,60,809 0/0:27,0:27:69:0,69,1035 0/0:23,0:23:66:0,66,790 0/0:20,0:20:60:0,60,697 0/0:21,0:21:60:0,60,880 0/0:26,0:26:60:0,60,900 0/0:21,0:21:63:0,63,691 0/0:22,0:22:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 +20 10385849 rs74703166 C A 6983.09 PASS HWP=0.6229;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.72;AN=200;InbreedingCoeff=-0.0202;AF=0.021;GQ_STDDEV=39.01;FS=0.0;DP=6723;GQ_MEAN=27.09;POSITIVE_TRAIN_SITE;VQSLOD=4.23;ClippingRankSum=0.358;BaseQRankSum=-0.736;MLEAF=0.022;MLEAC=38;MQ=60.0;QD=22.53;DB;MQRankSum=0.358;CCC=1724;NCC=8 GT:AD:DP:GQ:PL 0/0:7,0:7:21:0,21,257 0/0:8,0:8:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:3,0:3:9:0,9,102 0/0:6,0:6:18:0,18,228 0/0:9,0:9:27:0,27,344 0/0:10,0:10:27:0,27,405 0/0:2,0:2:6:0,6,68 0/0:7,0:7:20:0,20,271 0/0:5,0:5:15:0,15,184 0/0:5,0:5:15:0,15,202 0/0:6,0:6:12:0,12,180 0/0:6,0:6:15:0,15,225 0/0:4,0:4:12:0,12,151 0/0:9,0:9:24:0,24,320 0/0:8,0:8:24:0,24,304 0/0:7,0:7:21:0,21,260 0/0:14,0:14:39:0,39,516 0/0:6,0:6:18:0,18,231 0/0:14,0:14:36:0,36,554 0/1:7,2:9:99:117,0,561 0/0:10,0:10:24:0,24,360 0/0:9,0:9:27:0,27,356 0/0:7,0:7:21:0,21,243 0/0:6,0:6:18:0,18,246 0/1:8,7:15:99:341,0,594 0/0:9,0:9:27:0,27,374 0/0:11,0:11:30:0,30,417 0/0:13,0:13:39:0,39,523 0/0:4,0:4:6:0,6,90 0/0:4,0:4:12:0,12,147 0/0:2,0:2:6:0,6,87 0/0:20,0:20:60:0,60,719 0/0:12,0:12:33:0,33,495 0/0:24,0:24:63:0,63,945 0/0:3,0:3:9:0,9,131 0/0:2,0:2:6:0,6,80 0/0:8,0:8:24:0,24,319 0/0:21,0:21:60:0,60,794 0/0:8,0:8:21:0,21,315 0/0:6,0:6:18:0,18,222 0/0:11,0:11:33:0,33,436 0/0:14,0:14:36:0,36,540 0/0:11,0:11:30:0,30,450 0/0:15,0:15:39:0,39,585 0/0:15,0:15:39:0,39,585 0/0:20,0:20:60:0,60,750 0/0:13,0:13:33:0,33,495 0/0:10,0:10:24:0,24,360 0/0:10,0:10:27:0,27,388 0/0:15,0:15:36:0,36,540 0/0:12,0:12:22:0,22,449 0/0:7,0:7:21:0,21,265 0/0:5,0:5:15:0,15,167 0/0:2,0:2:6:0,6,69 0/0:10,0:10:27:0,27,405 0/0:22,0:22:60:0,60,900 0/0:13,0:13:39:0,39,524 0/0:9,0:9:24:0,24,360 0/0:15,0:15:42:0,42,630 0/0:10,0:10:21:0,21,315 0/0:6,0:6:12:0,12,180 0/0:13,0:13:33:0,33,495 0/0:4,0:4:12:0,12,162 0/0:9,0:9:27:0,27,361 0/0:10,0:10:27:0,27,405 0/0:3,0:3:6:0,6,90 0/0:1,0:1:3:0,3,38 0/0:16,0:16:42:0,42,630 0/0:6,0:6:18:0,18,216 0/0:12,0:12:33:0,33,457 0/0:7,0:7:21:0,21,292 0/0:9,0:9:27:0,27,402 0/0:7,0:7:21:0,21,266 0/0:5,0:5:15:0,15,195 0/0:7,0:7:21:0,21,297 0/0:6,0:6:12:0,12,180 0/0:4,0:4:12:0,12,146 0/0:10,0:10:24:0,24,360 0/0:7,0:7:21:0,21,264 0/0:2,0:2:6:0,6,75 0/0:7,0:7:21:0,21,248 0/0:1,0:1:3:0,3,39 0/0:7,0:7:21:0,21,261 0/0:8,0:8:21:0,21,315 0/0:9,0:9:24:0,24,360 0/0:2,0:2:6:0,6,75 0/0:1,0:1:3:0,3,37 0/0:7,0:7:21:0,21,261 0/0:15,0:15:36:0,36,540 0/0:3,0:3:3:0,3,45 0/0:4,0:4:12:0,12,156 0/0:3,0:3:9:0,9,122 0/0:3,0:3:9:0,9,112 0/0:8,0:8:21:0,21,315 0/0:9,0:9:27:0,27,286 0/0:4,0:4:12:0,12,147 0/0:8,0:8:24:0,24,296 0/0:2,0:2:6:0,6,87 0/0:7,0:7:21:0,21,286 +20 10385857 rs79940214 T C 6981.43 PASS HWP=0.6229;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.322;AN=200;InbreedingCoeff=-0.0187;AF=0.021;GQ_STDDEV=39.03;FS=0.0;DP=7264;GQ_MEAN=28.84;POSITIVE_TRAIN_SITE;VQSLOD=4.88;ClippingRankSum=0.406;BaseQRankSum=1.66;MLEAF=0.022;MLEAC=38;MQ=60.0;QD=18.92;DB;MQRankSum=0.248;CCC=1724;NCC=8 GT:AD:DP:GQ:PL 0/0:7,0:7:15:0,15,225 0/0:8,0:8:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:3,0:3:9:0,9,102 0/0:8,0:8:24:0,24,300 0/0:9,0:9:27:0,27,344 0/0:10,0:10:27:0,27,405 0/0:2,0:2:6:0,6,68 0/0:7,0:7:20:0,20,271 0/0:7,0:7:18:0,18,270 0/0:5,0:5:15:0,15,202 0/0:6,0:6:12:0,12,180 0/0:6,0:6:15:0,15,225 0/0:8,0:8:24:0,24,274 0/0:9,0:9:24:0,24,320 0/0:8,0:8:24:0,24,304 0/0:7,0:7:21:0,21,260 0/0:14,0:14:39:0,39,516 0/0:8,0:8:24:0,24,299 0/0:14,0:14:36:0,36,554 0/1:9,4:13:99:117,0,561 0/0:10,0:10:24:0,24,360 0/0:9,0:9:27:0,27,356 0/0:7,0:7:21:0,21,243 0/0:8,0:8:24:0,24,309 0/1:9,9:18:99:341,0,594 0/0:9,0:9:27:0,27,374 0/0:11,0:11:30:0,30,417 0/0:13,0:13:39:0,39,523 0/0:4,0:4:6:0,6,90 0/0:4,0:4:12:0,12,147 0/0:2,0:2:6:0,6,87 0/0:20,0:20:60:0,60,719 0/0:12,0:12:33:0,33,495 0/0:24,0:24:63:0,63,945 0/0:3,0:3:9:0,9,131 0/0:2,0:2:6:0,6,80 0/0:8,0:8:24:0,24,319 0/0:21,0:21:60:0,60,794 0/0:12,0:12:17:0,17,388 0/0:6,0:6:18:0,18,222 0/0:11,0:11:33:0,33,436 0/0:14,0:14:36:0,36,540 0/0:11,0:11:30:0,30,450 0/0:15,0:15:39:0,39,585 0/0:15,0:15:39:0,39,585 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,742 0/0:10,0:10:24:0,24,360 0/0:10,0:10:27:0,27,388 0/0:15,0:15:36:0,36,540 0/0:13,0:13:33:0,33,487 0/0:7,0:7:21:0,21,265 0/0:5,0:5:15:0,15,167 0/0:2,0:2:6:0,6,69 0/0:10,0:10:27:0,27,405 0/0:25,0:25:63:0,63,945 0/0:20,0:20:60:0,60,747 0/0:9,0:9:24:0,24,360 0/0:15,0:15:42:0,42,630 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,259 0/0:9,0:9:27:0,27,361 0/0:10,0:10:27:0,27,405 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,65 0/0:16,0:16:42:0,42,630 0/0:6,0:6:18:0,18,216 0/0:12,0:12:33:0,33,457 0/0:7,0:7:21:0,21,292 0/0:9,0:9:27:0,27,402 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,254 0/0:7,0:7:21:0,21,297 0/0:7,0:7:21:0,21,245 0/0:7,0:7:21:0,21,236 0/0:10,0:10:24:0,24,360 0/0:8,0:8:21:0,21,315 0/0:2,0:2:6:0,6,75 0/0:7,0:7:18:0,18,270 0/0:2,0:2:6:0,6,75 0/0:7,0:7:21:0,21,261 0/0:8,0:8:21:0,21,315 0/0:9,0:9:24:0,24,360 0/0:4,0:4:12:0,12,142 0/0:1,0:1:3:0,3,37 0/0:7,0:7:21:0,21,261 0/0:15,0:15:36:0,36,540 0/0:2,0:2:6:0,6,72 0/0:4,0:4:12:0,12,156 0/0:3,0:3:9:0,9,122 0/0:3,0:3:9:0,9,112 0/0:8,0:8:21:0,21,315 0/0:9,0:9:27:0,27,286 0/0:4,0:4:12:0,12,147 0/0:8,0:8:24:0,24,296 0/0:2,0:2:6:0,6,87 0/0:7,0:7:21:0,21,286 +20 10386013 rs1545 C A 320680.00 PASS HWP=0.3013;AC=31;culprit=FS;MQ0=0;ReadPosRankSum=0.498;AN=200;InbreedingCoeff=0.0382;AF=0.189;GQ_STDDEV=421.01;FS=0.0;DP=34942;GQ_MEAN=315.93;POSITIVE_TRAIN_SITE;VQSLOD=7.04;ClippingRankSum=-0.062;BaseQRankSum=-2.491;MLEAF=0.189;MLEAC=328;MQ=59.73;QD=14.68;DB;MQRankSum=0.072;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:37,38:75:99:1036,0,1133 0/1:45,35:80:99:1019,0,1312 0/0:21,0:21:60:0,60,847 0/1:47,24:71:99:649,0,1399 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:35,42:77:99:1295,0,1038 0/1:29,37:66:99:1016,0,886 0/0:23,0:23:60:0,60,900 0/1:34,33:67:99:944,0,1037 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,745 0/0:24,0:24:60:0,60,900 1/1:0,61:61:99:2039,183,0 0/0:21,0:21:60:0,60,775 0/0:28,0:28:62:0,62,945 0/1:43,35:78:99:1019,0,1230 1/1:1,75:76:99:2465,189,0 0/0:20,0:20:60:0,60,728 0/0:21,0:21:60:0,60,770 0/0:20,0:20:60:0,60,745 0/0:23,0:23:63:0,63,945 0/1:47,28:75:99:773,0,1449 0/0:21,0:21:63:0,63,797 0/0:20,0:20:60:0,60,748 0/0:20,0:20:60:0,60,726 0/0:30,0:30:77:0,77,1260 0/0:24,0:24:63:0,63,945 0/1:60,49:109:99:1327,0,1903 0/1:61,40:101:99:996,0,1788 0/0:22,0:22:60:0,60,900 0/0:21,0:21:63:0,63,701 0/0:20,0:20:60:0,60,719 0/1:69,63:132:99:1821,0,2102 0/0:24,0:24:63:0,63,945 0/1:38,27:65:99:675,0,1134 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,794 0/1:36,28:64:99:775,0,1016 0/0:29,0:29:63:0,63,1028 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,726 0/0:21,0:21:60:0,60,900 0/0:23,0:23:66:0,66,990 0/1:44,32:76:99:841,0,1392 0/0:24,0:24:60:0,60,900 0/1:41,36:77:99:1059,0,1172 0/0:33,0:33:63:0,63,990 0/0:21,0:21:60:0,60,850 0/0:21,0:21:60:0,60,745 0/0:23,0:23:60:0,60,945 0/0:20,0:20:60:0,60,730 0/1:31,32:63:99:861,0,1015 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,776 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,747 0/1:46,39:85:99:1100,0,1380 0/0:21,0:21:60:0,60,788 0/0:24,0:24:70:0,70,847 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,805 0/1:33,22:55:99:575,0,950 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,757 0/0:25,0:25:60:0,60,900 0/1:48,60:108:99:1683,0,1473 0/0:21,0:21:60:0,60,831 0/1:40,33:73:99:887,0,1218 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,744 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,710 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:63:0,63,782 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,793 0/0:21,0:21:60:0,60,861 0/1:42,52:94:99:1386,0,1201 0/0:21,0:21:60:0,60,697 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 1/1:0,75:75:99:2502,225,0 0/0:21,0:21:60:0,60,769 0/0:20,0:20:60:0,60,719 0/0:28,0:28:72:0,72,955 1/1:0,74:74:99:2549,222,0 0/0:23,0:23:66:0,66,866 0/1:19,11:30:99:294,0,582 0/1:34,35:69:99:1005,0,1019 0/0:27,0:27:63:0,63,945 0/0:28,0:28:60:0,60,900 +20 10386059 rs1547 G A 402472.00 PASS HWP=0.3433;AC=31;culprit=MQ;MQ0=0;ReadPosRankSum=0.302;AN=200;InbreedingCoeff=0.0352;AF=0.19;GQ_STDDEV=513.96;FS=1.094;DP=40817;GQ_MEAN=379.53;POSITIVE_TRAIN_SITE;VQSLOD=5.71;ClippingRankSum=0.042;BaseQRankSum=0.062;MLEAF=0.19;MLEAC=330;MQ=59.62;QD=14.52;DB;MQRankSum=0.129;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:48,38:86:99:1079,0,1318 0/1:52,33:85:99:949,0,1493 0/0:21,0:21:60:0,60,847 0/1:55,35:90:99:918,0,1569 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:44,37:81:99:1149,0,1246 0/1:40,45:85:99:1143,0,1093 0/0:23,0:23:60:0,60,900 0/1:54,33:87:99:925,0,1499 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,745 0/0:24,0:24:60:0,60,900 1/1:1,82:83:99:2763,246,0 0/0:21,0:21:60:0,60,775 0/0:28,0:28:62:0,62,945 0/1:54,50:104:99:1339,0,1498 1/1:0,84:84:99:2883,252,0 0/0:20,0:20:60:0,60,728 0/0:21,0:21:60:0,60,770 0/0:20,0:20:60:0,60,745 0/0:23,0:23:63:0,63,945 0/1:45,30:75:99:817,0,1263 0/0:21,0:21:63:0,63,797 0/0:20,0:20:60:0,60,748 0/0:20,0:20:60:0,60,726 0/0:30,0:30:77:0,77,1260 0/0:24,0:24:63:0,63,945 0/1:70,66:136:99:1867,0,1966 0/1:82,52:134:99:1384,0,2493 0/0:22,0:22:60:0,60,900 0/0:21,0:21:63:0,63,701 0/0:20,0:20:60:0,60,719 0/1:81,64:145:99:1771,0,2388 0/0:24,0:24:63:0,63,945 0/1:37,49:86:99:1218,0,869 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,794 0/1:45,40:85:99:1111,0,1215 0/0:29,0:29:63:0,63,1028 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,726 0/0:21,0:21:60:0,60,900 0/0:23,0:23:66:0,66,990 0/1:57,40:97:99:1060,0,1677 0/0:24,0:24:60:0,60,900 0/1:61,49:110:99:1248,0,1674 0/0:33,0:33:63:0,63,990 0/0:21,0:21:60:0,60,850 0/0:21,0:21:60:0,60,745 0/0:23,0:23:60:0,60,945 0/0:20,0:20:60:0,60,730 0/1:45,36:81:99:997,0,1336 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,776 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,747 0/1:55,53:108:99:1478,0,1557 0/0:21,0:21:60:0,60,788 0/0:24,0:24:70:0,70,847 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,805 0/1:31,23:54:99:648,0,913 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,757 0/0:25,0:25:60:0,60,900 0/1:60,65:125:99:1861,0,1587 0/0:21,0:21:60:0,60,831 0/1:50,40:90:99:1169,0,1292 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,744 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,710 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:63:0,63,782 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,793 0/0:21,0:21:60:0,60,861 0/1:59,66:125:99:1679,0,1625 0/0:21,0:21:60:0,60,697 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 1/1:0,121:121:99:3883,363,0 0/0:21,0:21:60:0,60,769 0/0:20,0:20:60:0,60,719 0/0:28,0:28:72:0,72,955 1/1:0,94:94:99:3066,282,0 0/0:23,0:23:66:0,66,866 0/1:22,21:43:99:599,0,663 0/1:52,33:85:99:842,0,1522 0/0:27,0:27:63:0,63,945 0/0:28,0:28:60:0,60,900 +20 10389422 rs145342800 T C 1798.70 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.567;AN=200;InbreedingCoeff=-0.0019;AF=0.001724;GQ_STDDEV=28.87;FS=0.737;DP=23205;GQ_MEAN=64.54;POSITIVE_TRAIN_SITE;VQSLOD=3.83;ClippingRankSum=-0.123;BaseQRankSum=1.58;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=14.39;DB;MQRankSum=-0.567;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:27,0:27:72:0,72,1080 0/0:32,0:32:87:0,87,1305 0/0:25,0:25:60:0,60,900 0/0:35,0:35:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/0:25,0:25:63:0,63,874 0/0:32,0:32:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,796 0/0:24,0:24:69:0,69,885 0/0:24,0:24:63:0,63,884 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:52,0:52:99:0,120,1800 0/0:36,0:36:93:0,93,1395 0/0:40,0:40:99:0,111,1499 0/0:40,0:40:99:0,111,1665 0/0:37,0:37:99:0,105,1575 0/0:46,0:46:99:0,120,1800 0/0:31,0:31:84:0,84,1260 0/0:41,0:41:99:0,114,1710 0/0:41,0:41:99:0,111,1665 0/0:27,0:27:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:29,0:29:64:0,64,1161 0/0:25,0:25:61:0,61,935 0/0:26,0:26:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,743 0/0:33,0:33:93:0,93,1374 0/0:18,0:18:44:0,44,675 0/0:31,0:31:60:0,60,900 0/0:23,0:23:60:0,60,874 0/0:9,0:9:21:0,21,315 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:47,0:47:99:0,111,1665 0/0:50,0:50:99:0,114,1710 0/0:28,0:28:60:0,60,900 0/0:29,0:29:65:0,65,1000 0/0:24,0:24:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:49,0:49:99:0,111,1665 0/0:23,0:23:60:0,60,814 0/0:25,0:25:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:24,0:24:63:0,63,851 0/0:44,0:44:99:0,112,1755 0/0:8,0:8:21:0,21,315 0/0:18,0:18:42:0,42,630 0/0:68,0:68:99:0,120,1800 0/0:28,0:28:62:0,62,990 0/0:27,0:27:67:0,67,1125 0/0:26,0:26:66:0,66,990 0/0:29,0:29:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:19,0:19:45:0,45,675 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:22,0:22:60:0,60,814 0/0:40,0:40:99:0,111,1611 0/1:19,29:48:99:937,0,586 0/0:29,0:29:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:21,0:21:60:0,60,746 0/0:27,0:27:63:0,63,945 0/0:28,0:28:65:0,65,990 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 +20 10389480 rs764266 T A 156293.00 PASS HWP=0.03;AC=33;culprit=MQ;MQ0=0;ReadPosRankSum=0.194;AN=200;InbreedingCoeff=0.0707;AF=0.244;GQ_STDDEV=172.8;FS=0.0;DP=18787;GQ_MEAN=133.07;POSITIVE_TRAIN_SITE;VQSLOD=6.79;ClippingRankSum=-0.091;BaseQRankSum=-1.379;MLEAF=0.245;MLEAC=426;MQ=60.0;QD=17.43;DB;MQRankSum=0.264;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:10,17:27:99:550,0,285 0/1:19,17:36:99:494,0,600 0/0:23,0:23:60:0,60,900 0/1:19,15:34:99:447,0,545 0/0:11,0:11:24:0,24,360 0/0:13,0:13:27:0,27,405 0/1:15,20:35:99:644,0,477 0/1:14,10:24:99:307,0,427 0/0:25,0:25:60:0,60,900 0/1:19,12:31:99:366,0,549 0/0:18,0:18:45:0,45,675 0/0:9,0:9:21:0,21,315 0/0:18,0:18:42:0,42,630 1/1:1,23:24:36:814,36,0 0/0:52,0:52:99:0,120,1800 0/0:36,0:36:93:0,93,1395 0/1:38,29:67:99:872,0,1192 1/1:0,97:97:99:3512,291,0 0/0:37,0:37:99:0,105,1575 0/0:46,0:46:99:0,120,1800 0/1:39,49:88:99:1496,0,1180 0/0:41,0:41:99:0,114,1710 0/1:40,32:72:99:986,0,1261 0/0:13,0:13:24:0,24,360 0/0:9,0:9:21:0,21,315 0/1:13,15:28:99:469,0,390 0/0:17,0:17:42:0,42,630 0/0:12,0:12:27:0,27,405 0/1:22,16:38:99:405,0,651 0/1:12,9:21:99:254,0,407 0/0:22,0:22:51:0,51,765 0/0:10,0:10:24:0,24,360 0/0:23,0:23:60:0,60,900 0/1:18,6:24:99:145,0,568 0/0:15,0:15:33:0,33,495 0/1:10,6:16:99:167,0,319 0/0:21,0:21:60:0,60,743 0/0:33,0:33:93:0,93,1374 0/0:12,0:12:21:0,21,315 0/1:7,3:10:79:79,0,247 0/0:11,0:11:21:0,21,315 0/0:8,0:8:21:0,21,278 0/0:8,0:8:21:0,21,270 0/0:14,0:14:30:0,30,450 0/0:23,0:23:60:0,60,900 0/1:11,11:22:99:343,0,333 0/0:13,0:13:39:0,39,497 0/1:10,11:21:99:319,0,339 0/0:47,0:47:99:0,111,1665 0/0:50,0:50:99:0,114,1710 0/0:12,0:12:30:0,30,450 0/0:11,0:11:24:0,24,360 0/0:12,0:12:27:0,27,405 0/1:5,11:16:99:352,0,150 0/0:11,0:11:21:0,21,315 0/0:14,0:14:36:0,36,540 0/0:12,0:12:27:0,27,405 0/0:13,0:13:36:0,36,534 0/1:6,10:16:99:301,0,195 0/0:49,0:49:99:0,111,1665 0/0:9,0:9:21:0,21,315 0/0:8,0:8:24:0,24,306 0/0:25,0:25:60:0,60,900 0/0:9,0:9:21:0,21,315 0/1:7,5:12:99:148,0,243 0/0:44,0:44:99:0,112,1755 0/0:6,0:6:15:0,15,225 0/0:4,0:4:9:0,9,135 0/1:33,35:68:99:1085,0,1054 0/0:9,0:9:21:0,21,315 0/1:17,10:27:99:297,0,540 0/0:8,0:8:21:0,21,315 0/0:16,0:16:33:0,33,495 0/0:12,0:12:27:0,27,405 0/0:10,0:10:21:0,21,315 0/0:3,0:3:9:0,9,109 0/0:12,0:12:27:0,27,405 0/0:11,0:11:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:17,0:17:30:0,30,450 0/0:5,0:5:12:0,12,180 0/0:8,0:8:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:16,0:16:27:0,27,405 0/0:11,0:11:30:0,30,450 0/0:13,0:13:24:0,24,360 0/1:11,13:24:99:361,0,323 0/0:22,0:22:60:0,60,814 0/0:40,0:40:99:0,111,1611 0/0:12,0:12:30:0,30,450 1/1:0,28:28:84:1002,84,0 0/0:24,0:24:63:0,63,945 0/0:14,0:14:24:0,24,450 0/0:7,0:7:21:0,21,255 1/1:0,29:29:87:1001,87,0 0/0:12,0:12:21:0,21,315 0/1:4,10:14:99:321,0,119 0/1:14,10:24:99:299,0,480 0/0:7,0:7:9:0,9,206 0/0:11,0:11:24:0,24,360 +20 10393145 rs221667 C G 873812.00 PASS HWP=0.0711;AC=46;culprit=QD;MQ0=0;ReadPosRankSum=0.458;AN=200;InbreedingCoeff=0.0638;AF=0.285;GQ_STDDEV=832.29;FS=1.46;DP=75314;GQ_MEAN=684.7;POSITIVE_TRAIN_SITE;VQSLOD=5.53;ClippingRankSum=-0.25;BaseQRankSum=2.56;MLEAF=0.285;MLEAC=496;MQ=59.67;QD=19.02;DB;MQRankSum=0.209;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:86,0:86:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/1:56,32:88:99:1005,0,1706 0/1:43,41:84:99:1354,0,1130 0/1:61,44:105:99:1391,0,1780 1/1:6,118:124:99:4450,273,0 0/0:93,0:93:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/1:70,67:137:99:2158,0,2132 0/1:47,40:87:99:1235,0,1299 0/1:57,50:107:99:1597,0,1636 1/1:0,93:93:99:3511,280,0 0/1:70,53:123:99:1699,0,2269 0/0:52,0:52:99:0,120,1800 1/1:0,54:54:99:1990,162,0 0/1:71,49:120:99:1486,0,2180 0/0:45,0:45:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/1:54,62:116:99:1983,0,1652 0/0:67,0:67:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:101,0:101:99:0,120,1800 0/1:58,42:100:99:1294,0,1800 0/0:42,0:42:99:0,105,1575 0/1:89,69:158:99:2383,0,2917 0/1:103,107:210:99:3683,0,3497 0/1:86,80:166:99:2888,0,2731 0/0:73,0:73:99:0,120,1800 1/1:0,105:105:99:3986,316,0 1/1:1,115:116:99:4139,309,0 0/0:63,0:63:99:0,120,1800 0/1:54,64:118:99:2175,0,1666 0/1:47,44:91:99:1450,0,1469 0/0:52,0:52:99:0,120,1800 0/1:41,40:81:99:1261,0,1259 0/0:64,0:64:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/1:50,44:94:99:1387,0,1543 0/1:48,45:93:99:1409,0,1496 0/1:49,59:108:99:1898,0,1481 0/0:68,0:68:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/1:55,31:86:99:1006,0,1725 0/0:80,0:80:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/1:71,55:126:99:1701,0,2313 0/0:93,0:93:99:0,120,1800 0/1:54,42:96:99:1404,0,1731 1/1:0,149:149:99:6083,448,0 0/1:41,39:80:99:1194,0,1313 0/0:56,0:56:98:0,98,1800 0/0:114,0:114:99:0,113,1800 0/1:52,39:91:99:1233,0,1579 0/0:62,0:62:99:0,120,1800 0/0:48,0:48:99:0,100,1620 0/0:36,0:36:90:0,90,1338 0/1:35,39:74:99:1355,0,1136 0/0:125,0:125:99:0,120,1800 0/0:37,0:37:84:0,84,1260 0/0:134,0:134:99:0,120,1800 0/1:48,39:87:99:1281,0,1595 0/0:90,0:90:99:0,120,1800 0/0:48,0:48:99:0,115,1800 0/1:69,54:123:99:1843,0,2443 0/0:33,0:33:71:0,71,1215 0/0:61,0:61:85:0,85,1800 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,118,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/1:37,34:71:99:1158,0,1265 0/0:26,0:26:66:0,66,884 0/0:55,0:55:99:0,120,1800 0/1:66,55:121:99:1805,0,2074 0/1:86,93:179:99:3022,0,2701 0/0:87,0:87:99:0,120,1800 0/1:75,56:131:99:1625,0,2378 0/0:63,0:63:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/1:61,62:123:99:1756,0,1839 0/0:49,0:49:95:0,95,1800 0/1:61,38:99:99:1293,0,2015 0/0:80,0:80:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/1:30,43:73:99:1488,0,1027 0/0:83,0:83:99:0,120,1800 0/0:30,0:30:71:0,71,1170 0/0:52,0:52:99:0,120,1800 +20 10393162 rs6133917 A C 565101.00 PASS HWP=0.2117;AC=31;culprit=MQ;MQ0=0;ReadPosRankSum=0.46;AN=200;InbreedingCoeff=0.0457;AF=0.189;GQ_STDDEV=768.62;FS=1.997;DP=68014;GQ_MEAN=549.13;POSITIVE_TRAIN_SITE;VQSLOD=5.7;ClippingRankSum=-0.103;BaseQRankSum=2.24;MLEAF=0.189;MLEAC=328;MQ=59.64;QD=15.0;DB;MQRankSum=0.27;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:87,71:158:99:2011,0,2500 0/1:72,56:128:99:1509,0,1966 0/0:39,0:39:99:0,102,1530 0/1:52,57:109:99:1624,0,1466 0/0:51,0:51:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/1:80,62:142:99:1983,0,2257 0/1:66,45:111:99:1358,0,1864 0/0:62,0:62:99:0,120,1800 0/1:49,57:106:99:1504,0,1413 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:99:0,108,1680 0/0:61,0:61:99:0,120,1800 1/1:1,91:92:99:3164,270,0 0/0:57,0:57:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:64,40:104:99:1088,0,1840 1/1:0,102:102:99:3363,306,0 0/0:49,0:49:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:55,0:55:99:0,120,1800 0/1:64,51:115:99:1363,0,1914 0/0:78,0:78:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/1:86,43:129:99:1249,0,2531 0/1:76,62:138:99:1737,0,2238 0/0:40,0:40:87:0,87,1392 0/0:42,0:42:99:0,105,1575 0/0:102,0:102:99:0,120,1800 0/1:137,125:262:99:3958,0,3909 0/0:86,0:86:99:0,120,1800 0/1:80,68:148:99:1782,0,2072 0/0:38,0:38:96:0,96,1440 0/0:53,0:53:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:76,54:130:99:1601,0,2339 0/0:43,0:43:65:0,65,1485 0/0:52,0:52:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/1:58,61:119:99:1892,0,1705 0/0:71,0:71:99:0,120,1800 0/1:73,57:130:99:1736,0,2080 0/0:68,0:68:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:43,0:43:99:0,111,1354 0/1:73,46:119:99:1411,0,2100 0/0:80,0:80:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/1:51,54:105:99:1587,0,1486 0/0:83,0:83:99:0,117,1800 0/0:61,0:61:62:0,62,1800 0/0:56,0:56:98:0,98,1800 0/0:114,0:114:99:0,113,1800 0/0:71,0:71:99:0,120,1800 0/1:62,37:99:99:1034,0,1798 0/0:48,0:48:99:0,100,1620 0/0:36,0:36:90:0,90,1338 0/0:27,0:27:63:0,63,945 0/1:103,89:192:99:2969,0,3101 0/0:37,0:37:84:0,84,1260 0/1:122,95:217:99:3095,0,3211 0/0:49,0:49:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:48,0:48:99:0,115,1800 0/0:48,0:48:94:0,94,1710 0/0:33,0:33:71:0,71,1215 0/0:61,0:61:85:0,85,1800 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,118,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/0:33,0:33:75:0,75,1125 0/0:26,0:26:66:0,66,884 0/0:55,0:55:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/1:81,81:162:99:2347,0,2208 0/0:31,0:31:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:109,0:109:99:0,120,1800 1/1:5,190:195:99:6619,506,0 0/0:39,0:39:90:0,90,1350 0/0:49,0:49:95:0,95,1800 0/0:43,0:43:99:0,111,1665 1/1:2,163:165:99:5645,446,0 0/0:27,0:27:60:0,60,900 0/1:52,38:90:99:1272,0,1568 0/1:75,43:118:99:1293,0,2232 0/0:30,0:30:71:0,71,1170 0/0:52,0:52:99:0,120,1800 +20 10393439 rs74315394 C A 2924.31 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=1.22;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=65.73;FS=6.745;DP=45018;GQ_MEAN=101.63;POSITIVE_TRAIN_SITE;VQSLOD=2.36;ClippingRankSum=-0.536;BaseQRankSum=-4.031;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=13.99;DB;MQRankSum=1.66;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:56,0:56:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:39,0:39:99:0,102,1530 0/0:50,0:50:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/0:58,0:58:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:41,0:41:91:0,91,1440 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:99:0,108,1680 0/0:61,0:61:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:44,0:44:99:0,108,1620 0/0:51,0:51:90:0,90,1800 0/0:49,0:49:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:55,0:55:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:56,0:56:99:0,115,1800 0/0:48,0:48:99:0,112,1710 0/0:40,0:40:87:0,87,1392 0/0:42,0:42:99:0,105,1575 0/0:102,0:102:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:38,0:38:96:0,96,1440 0/0:53,0:53:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:43,0:43:65:0,65,1485 0/0:52,0:52:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/1:42,52:94:99:1531,0,1302 0/0:43,0:43:99:0,111,1354 0/1:62,53:115:99:1470,0,1973 0/0:80,0:80:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:83,0:83:99:0,117,1800 0/0:61,0:61:62:0,62,1800 0/0:56,0:56:98:0,98,1800 0/0:114,0:114:99:0,113,1800 0/0:71,0:71:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:48,0:48:99:0,100,1620 0/0:36,0:36:90:0,90,1338 0/0:27,0:27:63:0,63,945 0/0:88,0:88:99:0,120,1800 0/0:37,0:37:84:0,84,1260 0/0:91,0:91:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:48,0:48:99:0,115,1800 0/0:48,0:48:94:0,94,1710 0/0:33,0:33:71:0,71,1215 0/0:61,0:61:85:0,85,1800 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,118,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/0:33,0:33:75:0,75,1125 0/0:26,0:26:66:0,66,884 0/0:55,0:55:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:28,0:28:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:38,0:38:75:0,75,1305 0/0:39,0:39:90:0,90,1350 0/0:49,0:49:95:0,95,1800 0/0:43,0:43:99:0,111,1665 0/0:33,0:33:84:0,84,1260 0/0:24,0:24:63:0,63,933 0/0:49,0:49:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:30,0:30:71:0,71,1170 0/0:52,0:52:99:0,120,1800 +20 10393629 rs17852625 G A 457848.00 PASS HWP=0.2449;AC=31;culprit=FS;MQ0=0;ReadPosRankSum=0.49;AN=200;InbreedingCoeff=0.0427;AF=0.187;GQ_STDDEV=627.51;FS=0.524;DP=59073;GQ_MEAN=457.93;POSITIVE_TRAIN_SITE;VQSLOD=5.55;ClippingRankSum=-0.345;BaseQRankSum=-3.806;MLEAF=0.187;MLEAC=325;MQ=59.66;QD=15.88;DB;MQRankSum=0.157;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:52,63:115:99:1758,0,1651 0/1:50,60:110:99:1823,0,1522 0/0:39,0:39:99:0,102,1530 0/1:70,42:112:99:1156,0,2044 0/0:51,0:51:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/1:54,44:98:99:1346,0,1675 0/1:38,36:74:99:1105,0,1192 0/0:62,0:62:99:0,120,1800 0/1:52,43:95:99:1235,0,1381 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:99:0,108,1680 0/0:61,0:61:99:0,120,1800 1/1:1,93:94:99:3326,280,0 0/0:57,0:57:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:34,26:60:99:748,0,1042 1/1:0,72:72:99:2609,217,0 0/0:49,0:49:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:55,0:55:99:0,120,1800 0/1:38,61:99:99:1793,0,1092 0/0:78,0:78:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/1:38,42:80:99:1308,0,1257 0/1:51,53:104:99:1517,0,1637 0/0:40,0:40:87:0,87,1392 0/0:42,0:42:99:0,105,1575 0/0:102,0:102:99:0,120,1800 0/1:149,100:249:99:2836,0,5138 0/0:86,0:86:99:0,120,1800 0/1:39,32:71:99:843,0,1158 0/0:38,0:38:96:0,96,1440 0/0:53,0:53:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:67,67:134:99:2066,0,2190 0/0:43,0:43:65:0,65,1485 0/0:52,0:52:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/1:54,77:131:99:2410,0,1739 0/0:71,0:71:99:0,120,1800 0/1:69,66:135:99:2029,0,2285 0/0:68,0:68:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:43,0:43:99:0,111,1354 0/1:65,47:112:99:1321,0,2253 0/0:80,0:80:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/1:89,70:159:99:2097,0,2843 0/0:83,0:83:99:0,117,1800 0/0:61,0:61:62:0,62,1800 0/0:56,0:56:98:0,98,1800 0/0:114,0:114:99:0,113,1800 0/0:71,0:71:99:0,120,1800 0/1:58,53:111:99:1587,0,1897 0/0:48,0:48:99:0,100,1620 0/0:36,0:36:90:0,90,1338 0/0:27,0:27:63:0,63,945 0/1:97,73:170:99:2242,0,3411 0/0:37,0:37:84:0,84,1260 0/1:112,86:198:99:2571,0,3726 0/0:49,0:49:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:48,0:48:99:0,115,1800 0/0:48,0:48:94:0,94,1710 0/0:33,0:33:71:0,71,1215 0/0:61,0:61:85:0,85,1800 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,118,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/0:33,0:33:75:0,75,1125 0/0:26,0:26:66:0,66,884 0/0:55,0:55:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/1:47,47:94:99:1350,0,1572 0/0:31,0:31:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:109,0:109:99:0,120,1800 1/1:0,112:112:99:3758,337,0 0/0:39,0:39:90:0,90,1350 0/0:49,0:49:95:0,95,1800 0/0:43,0:43:99:0,111,1665 1/1:0,84:84:99:2854,252,0 0/0:24,0:24:63:0,63,933 0/1:48,37:85:99:1087,0,1571 0/1:45,42:87:99:1280,0,1578 0/0:30,0:30:71:0,71,1170 0/0:52,0:52:99:0,120,1800 +20 10393680 rs79346251 T G 224.09 VQSRTrancheSNP99.95to100.00 HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=-2.349;AN=200;InbreedingCoeff=-0.0075;AF=0.004023;GQ_STDDEV=29.36;FS=279.749;DP=46479;GQ_MEAN=93.36;VQSLOD=-664.9;ClippingRankSum=2.12;BaseQRankSum=-5.204;MLEAF=0.003448;MLEAC=6;MQ=59.62;QD=0.33;DB;MQRankSum=0.407;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:55,0:55:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:39,0:39:99:0,102,1530 0/0:52,0:52:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/0:47,0:47:99:0,108,1800 0/0:55,0:55:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:99:0,108,1680 0/0:61,0:61:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:55,0:55:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/1:169,53:222:41:41,0,5039 0/0:158,41:199:69:0,69,5014 0/0:71,0:71:41:0,41,2269 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:38,0:38:93:0,93,1395 0/0:43,0:43:99:0,99,1402 0/0:40,0:40:87:0,87,1392 0/0:42,0:42:99:0,105,1575 0/0:102,0:102:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:36,0:36:93:0,93,1275 0/0:38,0:38:96:0,96,1440 0/0:53,0:53:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:43,0:43:65:0,65,1485 0/1:55,21:76:99:121,0,1670 0/0:80,0:80:59:0,59,2442 0/0:64,0:64:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:101,0:101:0:0,0,2897 0/0:68,0:68:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:81,0:81:30:0,30,2523 0/0:61,0:61:99:0,120,1800 0/0:43,0:43:99:0,111,1354 0/0:63,0:63:78:0,78,1800 0/0:80,0:80:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:96,0:96:45:0,45,2849 0/0:103,30:133:12:0,12,3420 0/0:108,0:108:6:0,6,3208 0/0:83,0:83:99:0,117,1800 0/0:61,0:61:62:0,62,1800 0/0:56,0:56:98:0,98,1800 0/0:114,0:114:99:0,113,1800 0/0:71,0:71:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,100,1620 0/0:36,0:36:90:0,90,1338 0/0:40,0:40:31:0,31,1153 0/0:89,0:89:99:0,120,1800 0/0:37,0:37:84:0,84,1260 0/0:100,0:100:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:48,0:48:99:0,115,1800 0/0:48,0:48:94:0,94,1710 0/0:33,0:33:71:0,71,1215 0/0:61,0:61:85:0,85,1800 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,118,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/0:33,0:33:75:0,75,1125 0/0:26,0:26:66:0,66,884 0/0:55,0:55:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:31,0:31:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:46,0:46:99:0,103,1515 0/0:39,0:39:90:0,90,1350 0/0:49,0:49:95:0,95,1800 0/0:57,0:57:59:0,59,1833 0/0:46,0:46:99:0,117,1755 0/0:24,0:24:63:0,63,933 0/0:41,0:41:99:0,108,1620 0/0:46,0:46:89:0,89,1575 0/0:30,0:30:71:0,71,1170 0/0:52,0:52:99:0,120,1800 +20 10394046 rs16991547 G A 492185.00 PASS HWP=0.015;AC=33;culprit=FS;MQ0=0;ReadPosRankSum=0.348;AN=200;InbreedingCoeff=0.0861;AF=0.245;GQ_STDDEV=517.72;FS=0.536;DP=53580;GQ_MEAN=430.01;POSITIVE_TRAIN_SITE;VQSLOD=5.8;ClippingRankSum=-0.112;BaseQRankSum=-2.911;MLEAF=0.245;MLEAC=426;MQ=59.75;QD=18.49;DB;MQRankSum=0.128;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:40,33:73:99:1002,0,1275 0/1:43,41:84:99:1175,0,1327 0/0:39,0:39:99:0,102,1530 0/1:26,39:65:99:1162,0,747 0/0:51,0:51:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/1:42,44:86:99:1365,0,1423 0/1:29,36:65:99:1130,0,947 0/0:62,0:62:99:0,120,1800 0/1:30,39:69:99:1172,0,923 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:99:0,108,1680 0/0:61,0:61:99:0,120,1800 1/1:1,65:66:99:2463,196,0 0/0:57,0:57:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:31,37:68:99:1159,0,988 1/1:0,73:73:99:2626,220,0 0/0:49,0:49:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/1:44,47:91:99:1415,0,1418 0/0:55,0:55:99:0,120,1800 0/1:60,66:126:99:2098,0,1833 0/0:90,0:90:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/1:38,44:82:99:1452,0,1228 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/1:38,39:77:99:1180,0,1315 0/1:39,42:81:99:1315,0,1289 0/0:40,0:40:87:0,87,1392 0/0:42,0:42:99:0,105,1575 0/0:102,0:102:99:0,120,1800 0/1:69,73:142:99:2414,0,2395 0/0:86,0:86:99:0,120,1800 0/1:25,20:45:99:563,0,800 0/0:38,0:38:96:0,96,1440 0/0:53,0:53:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:54,71:125:99:2344,0,1721 0/0:43,0:43:65:0,65,1485 0/0:55,0:55:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/1:59,62:121:99:2058,0,1906 0/0:71,0:71:99:0,120,1800 0/1:47,46:93:99:1467,0,1560 0/0:68,0:68:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:43,0:43:99:0,111,1354 0/1:44,37:81:99:1185,0,1587 0/0:80,0:80:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/1:52,47:99:99:1550,0,1754 0/0:83,0:83:99:0,117,1800 0/0:61,0:61:62:0,62,1800 0/0:56,0:56:98:0,98,1800 0/0:114,0:114:99:0,113,1800 0/0:71,0:71:99:0,120,1800 0/1:46,40:86:99:1301,0,1499 0/0:48,0:48:99:0,100,1620 0/0:36,0:36:90:0,90,1338 0/0:42,0:42:96:0,96,1336 0/1:77,68:145:99:2221,0,2592 0/0:37,0:37:84:0,84,1260 0/1:76,53:129:99:1664,0,2602 0/0:49,0:49:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:48,0:48:99:0,115,1800 0/0:48,0:48:94:0,94,1710 0/0:33,0:33:71:0,71,1215 0/0:61,0:61:85:0,85,1800 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,118,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/0:33,0:33:75:0,75,1125 0/0:26,0:26:66:0,66,884 0/0:55,0:55:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/1:28,37:65:99:1153,0,940 0/0:31,0:31:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:109,0:109:99:0,120,1800 1/1:0,72:72:99:2749,217,0 0/0:39,0:39:90:0,90,1350 0/0:49,0:49:95:0,95,1800 0/0:49,0:49:99:0,114,1710 1/1:0,63:63:99:2354,189,0 0/0:24,0:24:63:0,63,933 0/1:33,36:69:99:1207,0,1148 0/1:34,36:70:99:1192,0,1176 0/0:30,0:30:71:0,71,1170 0/0:52,0:52:99:0,120,1800 +20 10438897 . G A 22360.80 PASS HWP=0.3209;AC=2;culprit=ReadPosRankSum;MQ0=0;ReadPosRankSum=0.127;AN=200;InbreedingCoeff=0.0665;AF=0.014;GQ_STDDEV=137.85;FS=2.102;DP=38477;GQ_MEAN=110.57;VQSLOD=3.68;ClippingRankSum=-0.271;BaseQRankSum=-2.887;MLEAF=0.014;MLEAC=25;MQ=59.57;QD=12.32;MQRankSum=-0.025;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:70:0,70,1215 0/0:43,0:43:99:0,99,1485 0/0:33,0:33:90:0,90,1350 0/0:45,0:45:99:0,108,1620 0/0:35,0:35:71:0,71,1350 0/0:35,0:35:69:0,69,1215 0/0:40,0:40:96:0,96,1440 0/0:33,0:33:69:0,69,1170 0/0:49,0:49:99:0,120,1800 0/0:27,0:27:72:0,72,1080 0/0:56,0:56:99:0,120,1800 0/0:29,0:29:69:0,69,1035 0/0:64,0:64:99:0,120,1800 0/1:31,29:60:99:822,0,978 0/0:34,0:34:84:0,84,1260 0/0:53,0:53:82:0,82,1755 0/0:46,0:46:99:0,107,1710 0/1:54,39:93:99:1083,0,1561 0/0:61,0:61:99:0,105,1800 0/0:72,0:72:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:56,0:56:74:0,74,1800 0/0:73,0:73:61:0,61,1800 0/0:47,0:47:71:0,71,1575 0/0:37,0:37:74:0,74,1350 0/0:54,0:54:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:51,0:51:72:0,72,1758 0/0:83,0:83:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:44,0:44:77:0,77,1681 0/0:33,0:33:67:0,67,1125 0/0:59,0:59:99:0,116,1800 0/0:53,0:53:99:0,113,1800 0/0:59,0:59:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:43,0:43:70:0,70,1440 0/0:77,0:77:99:0,120,1800 0/0:39,0:39:96:0,96,1440 0/0:55,0:55:77:0,77,1800 0/0:27,0:27:60:0,60,900 0/0:35,0:35:87:0,87,1305 0/0:40,0:40:99:0,106,1628 0/0:40,0:40:88:0,88,1575 0/0:41,0:41:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:38,0:38:90:0,90,1350 0/0:60,0:60:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:41,0:41:99:0,105,1575 0/0:24,0:24:60:0,60,900 0/0:29,0:29:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:53,0:53:83:0,83,1800 0/0:47,0:47:99:0,108,1620 0/0:42,0:42:99:0,111,1665 0/0:36,0:36:83:0,83,1305 0/0:43,0:43:99:0,115,1495 0/0:57,0:57:99:0,120,1800 0/0:27,0:27:64:0,64,1001 0/0:30,0:30:75:0,75,1125 0/0:54,0:54:99:0,120,1800 0/0:29,0:29:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:56,0:56:99:0,120,1800 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:51,0:51:99:0,120,1800 0/0:35,0:35:69:0,69,1260 0/0:61,0:61:99:0,120,1800 0/0:34,0:34:84:0,84,1260 0/0:37,0:37:65:0,65,1260 0/0:30,0:30:78:0,78,1170 0/0:39,0:39:96:0,96,1440 0/0:34,0:34:65:0,65,1215 0/0:48,0:48:81:0,81,1755 0/0:48,0:48:99:0,114,1710 0/0:25,0:25:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:36,0:36:68:0,68,1350 0/0:33,0:33:75:0,75,1125 0/0:65,0:65:99:0,120,1800 0/0:30,0:30:69:0,69,1035 0/0:25,0:25:72:0,72,991 0/0:56,0:56:99:0,106,1800 0/0:52,0:52:99:0,110,1800 0/0:30,0:30:63:0,63,945 0/0:31,0:31:72:0,72,1080 0/0:42,0:42:99:0,99,1530 0/0:32,0:32:63:0,63,945 0/0:37,0:37:93:0,93,1395 0/0:22,0:22:60:0,60,736 0/0:26,0:26:66:0,66,916 0/0:37,0:37:84:0,84,1350 0/0:30,0:30:72:0,72,1080 0/0:35,0:35:90:0,90,1350 +20 10579373 rs78689061 C T 6550.33 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.942;AN=200;InbreedingCoeff=-0.0035;AF=0.003448;GQ_STDDEV=84.32;FS=5.985;DP=22226;GQ_MEAN=72.38;POSITIVE_TRAIN_SITE;VQSLOD=3.1;ClippingRankSum=-0.752;BaseQRankSum=0.55;MLEAF=0.003448;MLEAC=6;MQ=59.33;QD=12.72;DB;MQRankSum=-0.139;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:63:0,63,945 0/0:35,0:35:78:0,78,1345 0/0:26,0:26:63:0,63,934 0/0:29,0:29:66:0,66,990 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,863 0/0:26,0:26:63:0,63,945 0/0:22,0:22:60:0,60,827 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:21,0:21:63:0,63,736 0/0:20,0:20:60:0,60,746 0/0:20,0:20:60:0,60,670 0/0:20,0:20:60:0,60,740 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,783 0/0:37,0:37:90:0,90,1350 0/0:23,0:23:63:0,63,945 0/0:27,0:27:70:0,70,1080 0/0:25,0:25:69:0,69,889 0/0:21,0:21:60:0,60,799 0/0:20,0:20:60:0,60,705 0/0:23,0:23:66:0,66,781 0/0:22,0:22:63:0,63,945 0/0:22,0:22:66:0,66,841 0/0:27,0:27:66:0,66,990 0/0:31,0:31:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,922 0/0:26,0:26:75:0,75,1125 0/0:27,0:27:78:0,78,1170 0/0:24,0:24:69:0,69,1027 0/0:22,0:22:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:36,0:36:96:0,96,1440 0/0:22,0:22:66:0,66,870 0/0:21,0:21:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:20,0:20:60:0,60,751 0/0:34,0:34:84:0,84,1227 0/0:23,0:23:66:0,66,990 0/0:28,0:28:81:0,81,1009 0/0:22,0:22:66:0,66,844 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,776 0/0:35,0:35:99:0,99,1485 0/0:21,0:21:63:0,63,711 0/0:22,0:22:60:0,60,900 0/0:23,0:23:66:0,66,990 0/0:20,0:20:60:0,60,732 0/0:20,0:20:60:0,60,777 0/0:20,0:20:60:0,60,756 0/0:20,0:20:60:0,60,712 0/0:24,0:24:63:0,63,945 0/0:31,0:31:93:0,93,1251 0/0:24,0:24:72:0,72,860 0/0:21,0:21:60:0,60,900 0/0:30,0:30:65:0,65,1080 0/0:21,0:21:60:0,60,721 0/0:20,0:20:60:0,60,710 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,941 0/0:27,0:27:60:0,60,900 0/0:20,0:20:60:0,60,714 0/0:21,0:21:60:0,60,844 0/0:29,0:29:75:0,75,1062 0/0:21,0:21:60:0,60,900 0/0:27,0:27:72:0,72,1058 0/0:20,0:20:60:0,60,710 0/0:20,0:20:60:0,60,781 0/0:20,0:20:60:0,60,717 0/0:20,0:20:60:0,60,832 0/0:29,0:29:57:0,57,1026 0/0:20,0:20:60:0,60,661 0/0:24,0:24:63:0,63,945 0/0:20,0:20:60:0,60,748 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,866 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,752 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,728 0/0:25,0:25:75:0,75,934 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:29,0:29:87:0,87,1026 0/0:22,0:22:60:0,60,900 0/1:43,47:90:99:1226,0,1161 0/0:21,0:21:60:0,60,787 0/0:20,0:20:60:0,60,723 0/0:20,0:20:60:0,60,661 0/0:32,0:32:60:0,60,900 0/0:21,0:21:60:0,60,770 0/0:20,0:20:60:0,60,734 0/0:27,0:27:60:0,60,900 0/0:25,0:25:63:0,63,908 +20 10579398 rs140984471 C T 3043.31 PASS HWP=0.0172;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=-0.299;AN=200;InbreedingCoeff=0.3288;AF=0.003448;GQ_STDDEV=28.79;FS=1.452;DP=21988;GQ_MEAN=66.93;POSITIVE_TRAIN_SITE;VQSLOD=1.19;ClippingRankSum=-0.345;BaseQRankSum=-1.769;MLEAF=0.003448;MLEAC=6;MQ=60.0;QD=16.36;DB;MQRankSum=0.758;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:63:0,63,945 0/0:35,0:35:78:0,78,1345 0/0:26,0:26:63:0,63,934 0/0:29,0:29:66:0,66,990 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,863 0/0:26,0:26:63:0,63,945 0/0:22,0:22:60:0,60,827 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:21,0:21:63:0,63,736 0/0:20,0:20:60:0,60,746 0/0:20,0:20:60:0,60,670 0/0:20,0:20:60:0,60,740 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,783 0/0:37,0:37:90:0,90,1350 0/0:23,0:23:63:0,63,945 0/0:27,0:27:70:0,70,1080 0/0:25,0:25:69:0,69,889 0/0:21,0:21:60:0,60,799 0/0:20,0:20:60:0,60,705 0/0:23,0:23:66:0,66,781 0/0:22,0:22:63:0,63,945 0/0:22,0:22:66:0,66,841 0/0:27,0:27:66:0,66,990 0/0:31,0:31:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,922 0/0:26,0:26:75:0,75,1125 0/0:27,0:27:78:0,78,1170 0/0:24,0:24:69:0,69,1027 0/0:22,0:22:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:36,0:36:96:0,96,1440 1/1:0,43:43:99:1534,129,0 0/0:21,0:21:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:20,0:20:60:0,60,751 0/0:34,0:34:84:0,84,1227 0/0:23,0:23:66:0,66,990 0/0:28,0:28:81:0,81,1009 0/0:22,0:22:66:0,66,844 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,776 0/0:35,0:35:99:0,99,1485 0/0:21,0:21:63:0,63,711 0/0:22,0:22:60:0,60,900 0/0:23,0:23:66:0,66,990 0/0:20,0:20:60:0,60,732 0/0:20,0:20:60:0,60,777 0/0:20,0:20:60:0,60,756 0/0:20,0:20:60:0,60,712 0/0:24,0:24:63:0,63,945 0/0:31,0:31:93:0,93,1251 0/0:24,0:24:72:0,72,860 0/0:21,0:21:60:0,60,900 0/0:30,0:30:65:0,65,1080 0/0:21,0:21:60:0,60,721 0/0:20,0:20:60:0,60,710 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,941 0/0:27,0:27:60:0,60,900 0/0:20,0:20:60:0,60,714 0/0:26,0:26:60:0,60,887 0/0:29,0:29:75:0,75,1062 0/0:21,0:21:60:0,60,900 0/0:27,0:27:72:0,72,1058 0/0:20,0:20:60:0,60,710 0/0:20,0:20:60:0,60,781 0/0:20,0:20:60:0,60,717 0/0:20,0:20:60:0,60,832 0/0:24,0:24:51:0,51,815 0/0:20,0:20:60:0,60,661 0/0:24,0:24:63:0,63,945 0/0:20,0:20:60:0,60,748 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,866 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,752 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,728 0/0:25,0:25:75:0,75,934 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:29,0:29:87:0,87,1026 0/0:22,0:22:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:21,0:21:60:0,60,787 0/0:20,0:20:60:0,60,723 0/0:20,0:20:60:0,60,661 0/0:32,0:32:60:0,60,900 0/0:21,0:21:60:0,60,770 0/0:20,0:20:60:0,60,734 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,908 +20 10602009 rs75227075 A G 10503.30 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=-0.27;AN=200;InbreedingCoeff=-0.0093;AF=0.009195;GQ_STDDEV=88.6;FS=0.529;DP=22048;GQ_MEAN=73.33;POSITIVE_TRAIN_SITE;VQSLOD=3.4;ClippingRankSum=0.569;BaseQRankSum=-0.296;MLEAF=0.009195;MLEAC=16;MQ=60.0;QD=10.86;DB;MQRankSum=0.238;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:21,0:21:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:23,0:23:63:0,63,821 0/0:27,0:27:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:22,0:22:60:0,60,855 0/0:24,0:24:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:21,0:21:60:0,60,791 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:69:0,69,898 0/0:29,0:29:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:68:0,68,878 0/0:30,0:30:63:0,63,990 0/1:26,23:49:99:618,0,748 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,889 0/0:30,0:30:63:0,63,945 0/0:29,0:29:63:0,63,945 0/1:35,23:58:99:545,0,1124 0/0:27,0:27:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:29,0:29:70:0,70,1045 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:35,0:35:81:0,81,1215 0/0:27,0:27:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,716 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,753 0/0:26,0:26:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:22,0:22:60:0,60,808 0/0:27,0:27:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:35,0:35:75:0,75,1125 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:64:0,64,990 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:41,0:41:93:0,93,1395 0/0:29,0:29:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,921 0/0:24,0:24:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:21,0:21:60:0,60,760 0/0:31,0:31:77:0,77,1215 0/0:24,0:24:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:22,0:22:60:0,60,872 0/0:28,0:28:69:0,69,1035 0/0:23,0:23:63:0,63,864 0/0:23,0:23:60:0,60,891 0/0:21,0:21:60:0,60,797 0/0:21,0:21:60:0,60,870 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:21,0:21:60:0,60,793 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,865 0/0:22,0:22:60:0,60,820 0/0:21,0:21:60:0,60,900 0/0:28,0:28:64:0,64,1080 0/0:20,0:20:60:0,60,738 0/0:25,0:25:60:0,60,900 0/0:26,0:26:61:0,61,1035 0/0:29,0:29:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,858 0/0:21,0:21:60:0,60,791 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,733 0/0:22,0:22:60:0,60,877 +20 10603326 rs73075324 A G 60754.00 PASS HWP=0.4903;AC=13;culprit=FS;MQ0=0;ReadPosRankSum=1.09;AN=200;InbreedingCoeff=0.0369;AF=0.033;GQ_STDDEV=211.52;FS=0.544;DP=34180;GQ_MEAN=134.32;POSITIVE_TRAIN_SITE;VQSLOD=4.23;ClippingRankSum=-0.309;BaseQRankSum=4.01;MLEAF=0.033;MLEAC=58;MQ=59.6;QD=17.49;DB;MQRankSum=0.244;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:84:0,84,1260 0/0:23,0:23:63:0,63,945 0/0:29,0:29:75:0,75,1125 0/0:39,0:39:86:0,86,1349 0/0:30,0:30:79:0,79,1043 0/0:39,0:39:84:0,84,1349 0/0:36,0:36:93:0,93,1395 0/0:23,0:23:66:0,66,990 0/0:41,0:41:99:0,108,1620 0/0:28,0:28:66:0,66,990 0/0:33,0:33:84:0,84,1161 0/0:25,0:25:69:0,69,1035 0/0:33,0:33:90:0,90,1350 0/0:27,0:27:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:36,0:36:88:0,88,1324 0/0:45,0:45:99:0,111,1755 0/0:38,0:38:86:0,86,1438 0/1:22,20:42:99:637,0,597 0/0:41,0:41:99:0,111,1642 0/0:33,0:33:81:0,81,1215 0/0:33,0:33:74:0,74,1229 0/0:39,0:39:82:0,82,1378 0/1:74,78:152:99:2454,0,2189 0/1:71,60:131:99:1930,0,2156 0/0:51,0:51:99:0,120,1800 0/1:39,32:71:99:998,0,1266 0/1:20,30:50:99:1014,0,512 0/0:28,0:28:67:0,67,898 0/0:25,0:25:66:0,66,795 0/0:28,0:28:60:0,60,900 0/0:48,0:48:99:0,114,1710 0/0:69,0:69:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:42,0:42:87:0,87,1271 0/0:40,0:40:99:0,99,1485 0/0:51,0:51:99:0,120,1800 0/0:42,0:42:99:0,100,1453 0/0:60,0:60:99:0,120,1800 0/0:29,0:29:84:0,84,1168 0/0:34,0:34:82:0,82,1293 0/0:39,0:39:99:0,108,1461 0/0:43,0:43:99:0,108,1620 0/0:55,0:55:99:0,117,1800 0/0:47,0:47:99:0,120,1800 0/1:40,49:89:99:1674,0,1246 0/0:51,0:51:99:0,120,1800 0/0:43,0:43:99:0,104,1575 0/1:31,41:72:99:1498,0,948 0/0:38,0:38:99:0,102,1399 0/0:37,0:37:93:0,93,1395 0/1:39,44:83:99:1495,0,1240 0/0:38,0:38:90:0,90,1350 0/0:40,0:40:67:0,67,1297 0/0:38,0:38:99:0,102,1530 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:34,0:34:87:0,87,1305 0/0:45,0:45:99:0,109,1699 0/0:39,0:39:96:0,96,1494 0/0:74,0:74:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/1:35,33:68:99:1066,0,1068 0/1:36,28:64:99:899,0,1147 0/0:22,0:22:60:0,60,900 0/0:27,0:27:64:0,64,1080 0/0:49,0:49:99:0,114,1800 0/0:23,0:23:60:0,60,900 0/0:71,0:71:39:0,39,2289 0/1:27,15:42:99:499,0,871 0/1:38,34:72:99:1130,0,1175 0/0:24,0:24:60:0,60,900 0/0:27,0:27:69:0,69,973 0/0:21,0:21:60:0,60,749 0/0:33,0:33:77:0,77,1215 0/1:16,18:34:99:673,0,511 0/0:28,0:28:63:0,63,930 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,829 0/0:25,0:25:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:33,0:33:81:0,81,1161 0/0:31,0:31:81:0,81,1215 0/0:34,0:34:85:0,85,1440 0/0:42,0:42:99:0,108,1352 0/0:34,0:34:84:0,84,1260 0/0:46,0:46:99:0,101,1514 0/0:56,0:56:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:39,0:39:99:0,108,1620 0/0:37,0:37:90:0,90,1350 0/0:26,0:26:64:0,64,1023 0/0:39,0:39:99:0,102,1530 0/0:33,0:33:81:0,81,1215 0/0:23,0:23:60:0,60,900 0/0:31,0:31:63:0,63,1125 0/0:24,0:24:60:0,60,900 0/0:40,0:40:94:0,94,1395 +20 10603579 rs73896599 G A 63633.20 PASS HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.635;AN=200;InbreedingCoeff=0.0116;AF=0.029;GQ_STDDEV=275.28;FS=0.0;DP=37058;GQ_MEAN=151.54;POSITIVE_TRAIN_SITE;VQSLOD=6.1;ClippingRankSum=0.459;BaseQRankSum=-1.605;MLEAF=0.029;MLEAC=50;MQ=59.75;QD=13.95;DB;MQRankSum=0.504;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:84:0,84,1260 0/0:23,0:23:63:0,63,945 0/0:29,0:29:75:0,75,1125 0/0:39,0:39:86:0,86,1349 0/0:30,0:30:79:0,79,1043 0/0:39,0:39:84:0,84,1349 0/0:36,0:36:93:0,93,1395 0/0:23,0:23:66:0,66,990 0/0:41,0:41:99:0,108,1620 0/0:28,0:28:66:0,66,990 0/0:33,0:33:84:0,84,1161 0/0:25,0:25:69:0,69,1035 0/0:33,0:33:90:0,90,1350 0/0:27,0:27:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:36,0:36:88:0,88,1324 0/1:56,55:111:99:1543,0,1575 0/0:38,0:38:86:0,86,1438 0/0:41,0:41:99:0,100,1499 0/0:41,0:41:99:0,111,1642 0/0:33,0:33:81:0,81,1215 0/0:33,0:33:74:0,74,1229 0/0:39,0:39:82:0,82,1378 0/0:118,0:118:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:28,0:28:67:0,67,898 0/0:25,0:25:66:0,66,795 0/0:28,0:28:60:0,60,900 0/0:48,0:48:99:0,114,1710 0/0:69,0:69:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/1:47,31:78:99:840,0,1299 0/0:40,0:40:99:0,99,1485 0/0:51,0:51:99:0,120,1800 0/0:42,0:42:99:0,100,1453 0/0:60,0:60:99:0,120,1800 0/0:29,0:29:84:0,84,1168 0/0:34,0:34:82:0,82,1293 0/0:39,0:39:99:0,108,1461 0/0:43,0:43:99:0,108,1620 0/0:55,0:55:99:0,117,1800 0/0:47,0:47:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:43,0:43:99:0,104,1575 0/0:70,0:70:99:0,120,1800 0/0:38,0:38:99:0,102,1399 0/0:37,0:37:93:0,93,1395 0/0:84,0:84:99:0,120,1800 0/0:38,0:38:90:0,90,1350 0/0:40,0:40:67:0,67,1297 0/0:38,0:38:99:0,102,1530 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:34,0:34:87:0,87,1305 0/0:45,0:45:99:0,109,1699 0/0:39,0:39:96:0,96,1494 0/0:74,0:74:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:22,0:22:60:0,60,900 0/0:27,0:27:64:0,64,1080 0/0:49,0:49:99:0,114,1800 0/0:23,0:23:60:0,60,900 0/0:66,0:66:99:0,120,1800 0/0:47,0:47:99:0,116,1800 0/0:73,0:73:99:0,120,1800 0/0:24,0:24:60:0,60,900 0/0:27,0:27:69:0,69,973 0/0:21,0:21:60:0,60,749 0/0:33,0:33:77:0,77,1215 0/0:34,0:34:87:0,87,1305 0/0:28,0:28:63:0,63,930 0/0:27,0:27:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:28,0:28:72:0,72,1080 0/0:23,0:23:63:0,63,945 0/0:33,0:33:81:0,81,1161 0/0:31,0:31:81:0,81,1215 0/0:34,0:34:85:0,85,1440 0/0:42,0:42:99:0,108,1352 0/0:34,0:34:84:0,84,1260 0/0:46,0:46:99:0,101,1514 0/0:56,0:56:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:39,0:39:99:0,108,1620 0/0:37,0:37:90:0,90,1350 0/0:34,0:34:76:0,76,1195 0/0:39,0:39:99:0,102,1530 0/0:33,0:33:81:0,81,1215 0/0:33,0:33:71:0,71,1193 0/0:31,0:31:63:0,63,1125 0/0:24,0:24:60:0,60,900 0/0:40,0:40:94:0,94,1395 +20 10603750 rs6077853 G A 255018.00 PASS HWP=0.0979;AC=18;culprit=FS;MQ0=0;ReadPosRankSum=0.428;AN=200;InbreedingCoeff=0.0674;AF=0.07;GQ_STDDEV=649.91;FS=0.0;DP=46123;GQ_MEAN=317.98;POSITIVE_TRAIN_SITE;VQSLOD=7.21;ClippingRankSum=-0.261;BaseQRankSum=-0.291;MLEAF=0.07;MLEAC=121;MQ=59.6;QD=14.77;DB;MQRankSum=0.538;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:84:0,84,1260 0/0:23,0:23:63:0,63,945 0/0:29,0:29:75:0,75,1125 0/0:39,0:39:86:0,86,1349 0/0:30,0:30:79:0,79,1043 0/0:39,0:39:84:0,84,1349 0/0:36,0:36:93:0,93,1395 0/0:23,0:23:66:0,66,990 0/0:41,0:41:99:0,108,1620 0/0:28,0:28:66:0,66,990 0/0:33,0:33:84:0,84,1161 0/0:25,0:25:69:0,69,1035 0/0:33,0:33:90:0,90,1350 0/0:27,0:27:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:36,0:36:88:0,88,1324 0/0:42,0:42:96:0,96,1440 0/0:38,0:38:86:0,86,1438 0/1:57,79:136:99:2195,0,1536 0/0:41,0:41:99:0,111,1642 0/0:33,0:33:81:0,81,1215 0/0:33,0:33:74:0,74,1229 0/0:39,0:39:82:0,82,1378 0/1:111,96:207:99:2493,0,3331 0/1:118,95:213:99:2575,0,3500 0/0:51,0:51:99:0,120,1800 0/1:84,74:158:99:2237,0,2440 0/1:76,66:142:99:1899,0,2102 0/0:28,0:28:67:0,67,898 0/0:25,0:25:66:0,66,795 0/0:28,0:28:60:0,60,900 0/0:48,0:48:99:0,114,1710 0/0:69,0:69:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:32,0:32:84:0,84,1260 0/0:40,0:40:99:0,99,1485 0/1:89,90:179:99:2541,0,2567 0/0:42,0:42:99:0,100,1453 0/0:60,0:60:99:0,120,1800 0/0:29,0:29:84:0,84,1168 0/0:34,0:34:82:0,82,1293 0/0:39,0:39:99:0,108,1461 0/0:43,0:43:99:0,108,1620 0/0:55,0:55:99:0,117,1800 0/0:47,0:47:99:0,120,1800 0/1:95,94:189:99:2827,0,2841 0/0:51,0:51:99:0,120,1800 0/0:43,0:43:99:0,104,1575 0/1:98,98:196:99:2845,0,2830 0/0:38,0:38:99:0,102,1399 0/0:37,0:37:93:0,93,1395 0/1:69,65:134:99:1954,0,2123 0/0:38,0:38:90:0,90,1350 0/0:40,0:40:67:0,67,1297 0/0:38,0:38:99:0,102,1530 0/0:51,0:51:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:34,0:34:87:0,87,1305 0/0:45,0:45:99:0,109,1699 0/0:39,0:39:96:0,96,1494 0/1:148,122:270:99:3385,0,4615 0/0:46,0:46:99:0,120,1800 0/1:92,93:185:99:2762,0,2713 0/1:90,79:169:99:2230,0,2481 0/0:22,0:22:60:0,60,900 0/0:27,0:27:64:0,64,1080 0/0:49,0:49:99:0,114,1800 0/0:23,0:23:60:0,60,900 0/0:66,0:66:99:0,120,1800 0/1:61,72:133:99:1960,0,1886 0/1:107,108:215:99:3042,0,3182 0/0:24,0:24:60:0,60,900 0/0:27,0:27:69:0,69,973 0/1:58,45:103:99:1243,0,1657 0/1:66,76:142:99:2116,0,1924 0/1:64,66:130:99:1887,0,1831 0/0:28,0:28:63:0,63,930 0/0:27,0:27:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:28,0:28:72:0,72,1080 0/0:23,0:23:63:0,63,945 0/0:33,0:33:81:0,81,1161 0/0:31,0:31:81:0,81,1215 0/0:34,0:34:85:0,85,1440 0/0:42,0:42:99:0,108,1352 0/0:34,0:34:84:0,84,1260 0/0:46,0:46:99:0,101,1514 0/1:150,115:265:99:3338,0,4593 0/0:52,0:52:99:0,120,1800 0/0:39,0:39:99:0,108,1620 0/0:37,0:37:90:0,90,1350 0/0:34,0:34:76:0,76,1195 0/0:39,0:39:99:0,102,1530 0/0:33,0:33:81:0,81,1215 0/0:33,0:33:71:0,71,1193 0/0:31,0:31:63:0,63,1125 0/0:24,0:24:60:0,60,900 0/0:40,0:40:94:0,94,1395 +20 10620275 rs1051421 G A 805191.00 PASS HWP=0.0274;AC=42;culprit=FS;MQ0=0;ReadPosRankSum=0.673;AN=200;InbreedingCoeff=0.0799;AF=0.179;GQ_STDDEV=1161.47;FS=0.536;DP=86525;GQ_MEAN=766.81;POSITIVE_TRAIN_SITE;VQSLOD=6.03;ClippingRankSum=-0.236;BaseQRankSum=-6.226;MLEAF=0.179;MLEAC=311;MQ=59.64;QD=15.9;DB;MQRankSum=0.088;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:76,93:169:99:2629,0,2282 0/1:108,85:193:99:2311,0,3374 0/0:62,0:62:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:23,0:23:60:0,60,900 0/1:115,115:230:99:3306,0,3743 0/1:106,92:198:99:2562,0,3089 0/0:100,0:100:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:24,0:24:63:0,63,945 0/0:86,0:86:99:0,120,1800 0/0:34,0:34:84:0,84,1260 0/0:52,0:52:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:27,0:27:63:0,63,964 0/0:74,0:74:99:0,120,1800 0/1:101,141:242:99:4242,0,2909 0/0:92,0:92:99:0,120,1800 0/1:65,99:164:99:2837,0,1900 0/0:88,0:88:99:0,120,1800 0/0:52,0:52:60:0,60,900 0/0:45,0:45:69:0,69,1035 0/0:42,0:42:72:0,72,1080 0/0:36,0:36:72:0,72,1080 0/0:39,0:39:72:0,72,1080 0/0:109,0:109:99:0,120,1800 0/1:123,140:263:99:3795,0,3865 0/0:92,0:92:99:0,120,1800 0/1:122,87:209:99:2328,0,3820 0/1:114,111:225:99:3139,0,3793 0/0:62,0:62:66:0,66,990 0/0:65,0:65:99:0,120,1800 0/0:44,0:44:99:0,120,1800 0/0:53,0:53:99:0,105,1575 0/0:81,0:81:99:0,120,1800 1/1:0,116:116:99:3994,348,0 0/1:88,87:175:99:2580,0,2746 0/1:56,75:131:99:2206,0,1662 0/1:70,65:135:99:1904,0,2185 0/0:45,0:45:69:0,69,1035 0/0:26,0:26:66:0,66,912 0/1:94,75:169:99:2192,0,3032 0/1:110,107:217:99:3137,0,3474 0/0:41,0:41:99:0,108,1620 0/1:102,105:207:99:2976,0,3188 0/0:58,0:58:63:0,63,945 0/1:117,156:273:99:4631,0,3797 0/0:42,0:42:63:0,63,990 0/0:30,0:30:75:0,75,1125 0/0:27,0:27:69:0,69,923 0/1:84,89:173:99:2503,0,2807 0/1:92,112:204:99:3156,0,3132 0/1:83,82:165:99:2244,0,2607 0/0:28,0:28:63:0,63,945 0/1:107,104:211:99:3071,0,3362 0/1:124,87:211:99:2400,0,4073 0/1:141,119:260:99:3452,0,4758 0/1:62,69:131:99:1974,0,1915 0/0:34,0:34:75:0,75,1125 0/0:63,0:63:75:0,75,1125 0/1:74,74:148:99:2093,0,2355 0/1:77,66:143:99:1833,0,2481 0/0:72,0:72:99:0,120,1800 0/0:34,0:34:96:0,96,1440 0/1:44,45:89:99:1266,0,1547 0/0:62,0:62:60:0,60,900 0/1:47,77:124:99:2255,0,1512 1/1:8,237:245:99:8199,712,0 0/0:33,0:33:63:0,63,945 0/0:43,0:43:69:0,69,1035 0/1:73,78:151:99:2215,0,2397 1/1:0,142:142:99:4827,427,0 0/0:29,0:29:75:0,75,1125 0/0:36,0:36:66:0,66,990 0/1:83,94:177:99:2581,0,2878 0/0:31,0:31:72:0,72,1080 0/1:66,95:161:99:2806,0,2124 0/0:27,0:27:81:0,81,1069 0/0:25,0:25:66:0,66,875 0/0:33,0:33:90:0,90,1183 0/0:38,0:38:66:0,66,990 0/0:38,0:38:63:0,63,945 0/1:114,112:226:99:3065,0,3798 0/1:95,73:168:99:1991,0,3106 0/0:48,0:48:99:0,108,1620 0/0:76,0:76:99:0,120,1800 0/1:130,147:277:99:4215,0,4310 0/1:132,89:221:99:2264,0,3857 0/0:50,0:50:99:0,120,1800 0/0:36,0:36:69:0,69,1035 0/1:67,57:124:99:1587,0,2320 0/0:30,0:30:66:0,66,990 0/1:82,76:158:99:2037,0,2498 0/0:23,0:23:63:0,63,945 0/0:34,0:34:99:0,99,1417 0/0:21,0:21:60:0,60,900 0/0:23,0:23:66:0,66,990 +20 10620386 rs1051419 A G 2023870.00 PASS HWP=3.0E-4;AC=130;culprit=FS;MQ0=0;ReadPosRankSum=0.256;AN=200;InbreedingCoeff=0.1282;AF=0.751;GQ_STDDEV=641.45;FS=0.589;DP=73082;GQ_MEAN=580.88;POSITIVE_TRAIN_SITE;VQSLOD=4.52;ClippingRankSum=-0.055;BaseQRankSum=2.08;MLEAF=0.751;MLEAC=1306;MQ=59.64;QD=28.7;DB;MQRankSum=0.237;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,78:78:99:2796,235,0 1/1:1,63:64:99:2301,189,0 0/1:26,32:58:99:960,0,780 0/1:45,39:84:99:1120,0,1298 0/1:31,38:69:99:1143,0,956 0/0:23,0:23:60:0,60,900 1/1:0,80:80:99:3132,241,0 1/1:0,79:79:99:2981,238,0 0/1:52,48:100:99:1580,0,1622 0/1:45,40:85:99:1250,0,1309 0/1:34,40:74:99:1164,0,1047 0/0:24,0:24:63:0,63,945 0/1:57,38:95:99:1161,0,1803 0/0:34,0:34:84:0,84,1260 1/1:0,74:74:99:2568,223,0 0/1:34,48:82:99:1535,0,940 0/1:44,41:85:99:1220,0,1328 0/0:27,0:27:63:0,63,964 0/1:44,29:73:99:877,0,1449 1/1:0,91:91:99:3407,274,0 1/1:0,88:88:99:3164,264,0 1/1:0,103:103:99:3627,310,0 0/1:43,53:96:99:1627,0,1373 0/1:93,80:173:99:2645,0,2883 0/1:69,95:164:99:3016,0,2077 1/1:0,114:114:99:4081,342,0 0/1:57,61:118:99:1788,0,1703 0/1:57,66:123:99:1985,0,1642 0/1:65,60:125:99:1920,0,1916 1/1:1,105:106:99:4002,283,0 0/1:58,55:113:99:1628,0,1610 1/1:0,58:58:99:2282,174,0 1/1:0,202:202:99:7522,607,0 0/1:105,89:194:99:2965,0,3149 0/1:81,76:157:99:2342,0,2418 0/1:32,28:60:99:791,0,957 1/1:0,54:54:99:2020,162,0 0/1:46,51:97:99:1605,0,1413 1/1:0,74:74:99:2737,222,0 0/1:58,67:125:99:2013,0,1806 0/1:37,41:78:99:1212,0,1068 0/1:47,51:98:99:1473,0,1439 0/1:39,34:73:99:1062,0,1183 0/1:53,62:115:99:1868,0,1634 0/1:59,55:114:99:1653,0,1829 0/1:61,54:115:99:1584,0,1911 1/1:0,89:89:99:3237,267,0 1/1:0,123:123:99:4335,369,0 1/1:0,137:137:99:5249,412,0 1/1:0,151:151:99:5678,454,0 1/1:0,111:111:99:3998,333,0 0/1:44,41:85:99:1245,0,1315 1/1:0,71:71:99:2598,214,0 0/1:41,33:74:99:1102,0,1247 0/1:63,58:121:99:1867,0,1922 1/1:1,101:102:99:3582,275,0 0/1:61,73:134:99:2284,0,1827 1/1:0,145:145:99:5345,435,0 0/1:70,72:142:99:2122,0,2044 0/1:70,46:116:99:1404,0,2225 0/1:41,48:89:99:1388,0,1244 0/1:49,54:103:99:1680,0,1466 0/1:85,90:175:99:2977,0,2560 0/1:39,54:93:99:1705,0,1115 1/1:0,79:79:99:2952,238,0 0/1:50,41:91:99:1260,0,1570 0/1:23,25:48:99:853,0,701 0/1:17,25:42:99:808,0,497 1/1:2,167:169:99:6436,502,0 1/1:1,77:78:99:2994,202,0 1/1:3,103:106:99:4150,310,0 1/1:0,80:80:99:3117,240,0 0/1:61,70:131:99:2153,0,1781 0/1:34,39:73:99:1316,0,1046 1/1:0,67:67:99:2649,202,0 1/1:0,66:66:99:2571,198,0 0/1:53,51:104:99:1720,0,1538 1/1:1,74:75:99:2888,189,0 0/1:35,41:76:99:1357,0,1072 1/1:0,88:88:99:3416,265,0 0/1:25,24:49:99:768,0,737 0/1:29,21:50:99:623,0,900 0/1:42,40:82:99:1312,0,1284 0/0:38,0:38:66:0,66,990 0/1:37,46:83:99:1485,0,1043 0/1:52,48:100:99:1560,0,1633 1/1:0,55:55:99:2164,166,0 0/1:25,25:50:99:808,0,774 0/1:46,29:75:99:840,0,1478 1/1:0,163:163:99:6392,490,0 1/1:0,70:70:99:2756,211,0 0/1:24,24:48:99:736,0,707 0/1:48,55:103:99:1836,0,1421 0/1:30,28:58:99:980,0,933 0/0:30,0:30:66:0,66,990 1/1:1,45:46:99:1675,100,0 1/1:0,77:77:99:2972,232,0 1/1:0,85:85:99:3350,256,0 0/1:32,29:61:99:962,0,938 0/0:23,0:23:66:0,66,990 +20 10621923 rs75617279 G GT 140656.00 PASS HWP=0.0156;AC=32;culprit=FS;MQ0=0;ReadPosRankSum=-0.283;AN=200;InbreedingCoeff=0.0953;AF=0.086;GQ_STDDEV=281.2;FS=0.0;DP=49421;GQ_MEAN=213.35;POSITIVE_TRAIN_SITE;VQSLOD=5.7;ClippingRankSum=-0.838;BaseQRankSum=0.0;MLEAF=0.086;MLEAC=150;MQ=60.2;QD=16.43;DB;MQRankSum=0.289;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:28,25:53:99:763,0,846 0/1:28,28:56:99:851,0,882 0/1:24,20:44:99:609,0,724 0/0:51,0:51:99:0,120,1800 0/1:28,30:58:99:909,0,867 0/0:48,0:48:99:0,120,1800 0/1:40,27:67:99:834,0,1252 0/1:25,26:51:99:769,0,774 0/1:36,39:75:99:1192,0,1122 0/0:50,0:50:99:0,120,1800 0/1:35,26:61:99:794,0,993 0/0:43,0:43:95:0,95,1549 0/1:46,31:77:99:955,0,1425 0/0:38,0:38:99:0,102,1530 0/0:63,0:63:99:0,120,1800 0/1:38,33:71:99:1018,0,1190 0/0:55,0:55:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:43,0:43:99:0,114,1710 0/0:70,0:70:99:0,120,1800 0/1:29,40:69:99:1280,0,876 0/0:96,0:96:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:31,36:67:99:1128,0,961 0/1:33,32:65:99:1008,0,1039 0/1:31,19:50:99:558,0,991 0/0:53,0:53:99:0,120,1800 0/0:98,0:98:99:0,120,1800 0/0:144,0:144:99:0,120,1800 0/1:57,55:112:99:1739,0,1784 0/0:44,0:44:99:0,105,1575 0/0:44,0:44:99:0,117,1755 0/0:72,0:72:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:46,0:46:99:0,108,1620 0/0:54,0:54:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/1:33,33:66:99:1029,0,1017 0/0:81,0:81:99:0,120,1800 0/1:29,19:48:99:554,0,937 0/0:62,0:62:99:0,120,1800 0/0:43,0:43:99:0,114,1710 0/0:56,0:56:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:49,0:49:99:0,117,1755 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/1:18,18:36:99:557,0,554 0/0:24,0:24:66:0,66,990 0/0:70,0:70:99:0,120,1800 0/1:21,24:45:99:778,0,650 0/0:83,0:83:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:42,0:42:99:0,102,1530 0/0:47,0:47:99:0,111,1665 0/0:53,0:53:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:25,0:25:63:0,63,945 0/1:32,17:49:99:474,0,1051 0/0:68,0:68:99:0,120,1800 0/1:34,23:57:99:680,0,1084 0/0:85,0:85:99:0,120,1800 0/1:21,19:40:99:612,0,661 0/1:29,18:47:99:521,0,932 0/1:50,35:85:99:1051,0,1599 0/0:104,0:104:99:0,120,1800 0/1:38,19:57:99:533,0,1228 0/0:37,0:37:84:0,84,1260 0/1:32,32:64:99:1000,0,1003 0/0:42,0:42:99:0,99,1485 0/0:37,0:37:87:0,87,1305 0/1:29,21:50:99:621,0,924 1/1:0,34:34:99:1253,104,0 1/1:3,52:55:52:1801,52,0 0/1:19,18:37:99:554,0,600 0/0:55,0:55:99:0,120,1800 +20 10622080 . C CA 567188.00 PASS HWP=0.054;AC=20;culprit=FS;MQ0=0;ReadPosRankSum=-0.086;AN=200;InbreedingCoeff=0.2878;AF=0.11;GQ_STDDEV=507.94;FS=0.0;DP=80607;GQ_MEAN=464.84;VQSLOD=3.74;ClippingRankSum=-0.602;BaseQRankSum=0.165;MLEAF=0.11;MLEAC=192;MQ=60.12;QD=13.84;DB;MQRankSum=0.499;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:45,0:84:99:0,129,1222 0/0:62,0:117:99:0,180,1680 0/0:100,0:100:30:0,30,3162 0/0:47,0:97:99:0,141,1325 0/0:41,0:41:90:0,90,1350 0/0:106,0:106:0:0,0,3362 0/0:56,5:112:99:0,271,2042 0/0:36,3:73:99:0,146,1267 0/0:40,0:40:96:0,96,1440 0/0:34,0:76:99:0,102,960 0/0:70,6:82:67:0,67,1828 0/0:30,0:30:60:0,60,900 0/0:114,0:114:47:0,47,3977 0/0:30,0:30:81:0,81,1215 0/0:79,7:91:77:0,77,2088 0/0:187,0:187:9:0,9,5542 0/0:25,0:25:63:0,63,945 0/0:176,0:176:7:0,7,5344 0/1:70,63:142:99:1588,0,1516 0/0:94,3:210:99:0,500,3671 0/1:62,5:144:99:1700,0,1359 0/0:77,3:171:99:0,397,2994 0/0:180,0:180:59:0,59,5555 0/1:86,81:173:99:1920,0,1809 0/1:111,3:207:99:2255,0,2491 0/1:26,31:57:99:633,0,565 0/1:48,40:91:99:893,0,1079 0/1:56,36:92:99:676,0,1302 0/0:40,0:40:82:0,82,1305 0/0:62,4:136:99:0,268,2317 0/0:33,0:33:78:0,78,1170 0/0:42,0:92:99:0,126,1170 0/0:66,4:136:99:0,276,2409 0/0:58,0:131:99:0,174,1644 0/0:70,0:70:99:0,120,1800 0/0:93,9:109:88:0,88,2432 0/0:116,0:116:0:0,0,3495 0/1:101,82:187:99:1906,0,2249 0/0:0,0:74:0:0,0,0 0/0:55,0:109:99:0,165,1548 0/0:36,0:68:99:0,108,1011 0/0:19,0:35:57:0,57,542 0/0:79,0:79:0:0,0,2505 0/0:62,0:62:99:0,120,1800 0/0:37,0:96:99:0,111,1036 0/0:54,0:111:99:0,163,1528 0/1:56,42:98:99:826,0,1290 0/0:2,0:102:6:0,6,56 0/0:56,0:56:98:0,98,1800 0/1:2,75:152:99:1608,0,343 0/0:80,0:80:99:0,120,1800 0/0:45,0:45:84:0,84,1575 0/1:30,21:51:99:428,0,695 0/0:44,0:83:99:0,132,1257 0/0:51,3:100:99:0,198,1806 0/0:0,0:76:0:0,0,0 0/0:82,0:82:99:0,120,1800 0/0:61,0:103:99:0,184,1722 0/0:45,0:91:99:0,135,1270 0/0:82,0:163:99:0,246,2321 0/0:32,0:72:95:0,95,895 0/0:61,0:61:99:0,119,1800 0/1:65,46:122:99:1140,0,1448 0/0:38,0:72:99:0,113,1047 0/1:0,30:70:99:655,0,191 0/1:77,58:149:99:1445,0,1700 0/0:28,0:28:63:0,63,945 0/0:23,0:39:69:0,69,655 0/0:79,0:79:99:0,120,1800 0/0:29,0:54:87:0,87,828 0/0:4,3:114:99:0,254,1069 0/1:43,23:66:99:363,0,1015 0/1:57,60:127:99:1295,0,1300 0/0:25,0:53:75:0,75,696 0/0:0,0:68:0:0,0,0 0/1:24,0:46:99:409,0,522 0/1:30,35:65:99:745,0,655 0/1:1,29:62:99:593,0,165 0/0:40,0:40:69:0,69,1035 0/0:34,3:86:99:0,155,1358 0/0:24,0:24:66:0,66,958 0/0:31,0:31:62:0,62,1038 0/0:27,0:27:66:0,66,981 0/0:41,0:41:64:0,64,1395 0/0:39,0:39:75:0,75,1395 0/0:51,0:96:99:0,153,1414 0/0:54,0:117:99:0,160,1471 0/0:72,6:86:88:0,88,1934 0/0:29,0:29:72:0,72,1080 0/1:3,50:134:99:1132,0,467 0/0:125,0:125:0:0,0,4156 0/0:70,9:88:28:0,28,1831 0/0:30,0:30:68:0,68,1035 0/0:20,0:61:60:0,60,571 0/0:60,5:69:69:0,69,1583 0/0:36,0:69:99:0,104,958 0/0:28,0:28:63:0,63,945 0/0:33,0:33:67:0,67,1125 0/0:35,0:35:63:0,63,945 0/0:35,0:35:81:0,81,1215 +20 10622080 . CA C 567188.00 PASS HWP=0.054;AC=46;culprit=FS;MQ0=0;ReadPosRankSum=-0.086;AN=200;InbreedingCoeff=0.2878;AF=0.189;GQ_STDDEV=507.94;FS=0.0;DP=80607;GQ_MEAN=464.84;VQSLOD=3.74;ClippingRankSum=-0.602;BaseQRankSum=0.165;MLEAF=0.191;MLEAC=333;MQ=60.12;QD=13.84;DB;MQRankSum=0.499;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:45,39:84:99:845,0,973 0/1:62,55:117:99:1213,0,1332 0/0:100,0:100:30:0,30,3162 0/1:47,50:97:99:1075,0,1036 0/0:41,0:41:90:0,90,1350 0/0:106,0:106:0:0,0,3362 0/1:56,51:112:99:1126,0,1385 0/1:36,34:73:99:761,0,828 0/0:40,0:40:96:0,96,1440 0/1:34,42:76:99:905,0,734 0/0:70,6:82:99:0,193,2183 0/0:30,0:30:60:0,60,900 0/0:114,0:114:47:0,47,3977 0/0:30,0:30:81:0,81,1215 0/0:79,5:91:99:0,142,2344 0/0:187,0:187:9:0,9,5542 0/0:25,0:25:63:0,63,945 0/0:176,0:176:7:0,7,5344 0/0:70,0:142:0:0,0,1695 0/1:94,113:210:99:2586,0,2255 0/0:62,4:144:99:0,306,2683 0/1:77,91:171:99:2094,0,1726 0/0:180,0:180:59:0,59,5555 0/0:86,0:173:66:0,66,2101 0/0:111,6:207:99:0,552,4355 0/0:26,0:57:81:0,81,738 0/0:48,0:91:99:0,103,1278 0/0:56,0:92:99:0,171,1580 0/0:40,0:40:82:0,82,1305 0/1:62,70:136:99:1590,0,1444 0/0:33,0:33:78:0,78,1170 0/1:42,50:92:99:1160,0,890 0/1:66,66:136:99:1485,0,1513 0/1:58,73:131:99:1688,0,1245 0/0:70,0:70:99:0,120,1800 0/0:93,7:109:99:0,184,2807 0/0:116,0:116:0:0,0,3495 0/0:101,0:187:99:0,131,2609 1/1:0,74:74:99:2099,225,0 0/1:55,54:109:99:1185,0,1218 0/1:36,32:68:99:714,0,804 0/1:19,16:35:99:356,0,436 0/0:79,0:79:0:0,0,2505 0/0:62,0:62:99:0,120,1800 0/1:37,59:96:99:1388,0,744 0/1:54,57:111:99:1302,0,1190 0/0:56,0:98:99:0,172,1587 1/1:2,100:102:99:2812,254,0 0/0:56,0:56:98:0,98,1800 0/1:2,75:152:99:1665,0,559 0/0:80,0:80:99:0,120,1800 0/0:45,0:45:84:0,84,1575 0/0:30,0:51:92:0,92,850 0/1:44,39:83:99:871,0,1005 0/1:51,46:100:99:1014,0,1210 1/1:0,76:76:99:2152,231,0 0/0:82,0:82:99:0,120,1800 0/1:61,42:103:99:892,0,1408 0/1:45,46:91:99:1038,0,994 0/1:82,81:163:99:1829,0,1827 0/1:32,40:72:99:929,0,677 0/0:61,0:61:99:0,119,1800 0/0:65,0:122:0:0,0,1576 0/1:38,34:72:99:758,0,829 0/1:0,40:70:99:947,0,193 0/0:77,0:149:2:0,2,1866 0/0:28,0:28:63:0,63,945 0/1:23,16:39:99:341,0,536 0/0:79,0:79:99:0,120,1800 0/1:29,25:54:99:554,0,663 1/1:4,107:114:99:2983,266,0 0/0:43,0:66:99:0,131,1214 0/0:57,10:127:99:0,193,2269 0/1:25,28:53:99:644,0,534 1/1:0,68:68:99:1951,206,0 0/0:24,0:46:40:0,40,614 0/0:30,0:65:93:0,93,852 0/1:1,32:62:99:733,0,195 0/0:40,0:40:69:0,69,1035 0/1:34,49:86:99:1140,0,792 0/0:24,0:24:66:0,66,958 0/0:31,0:31:62:0,62,1038 0/0:27,0:27:66:0,66,981 0/0:41,0:41:64:0,64,1395 0/0:39,0:39:75:0,75,1395 0/1:51,45:96:99:1005,0,1123 0/1:54,63:117:99:1420,0,1118 0/0:72,8:86:50:0,50,2087 0/0:29,0:29:72:0,72,1080 0/1:3,77:134:99:1809,0,434 0/0:125,0:125:0:0,0,4156 0/0:70,9:88:21:0,21,2003 0/0:30,0:30:68:0,68,1035 0/1:20,41:61:99:991,0,387 0/0:60,4:69:99:0,102,1777 0/1:36,33:69:99:725,0,751 0/0:28,0:28:63:0,63,945 0/0:33,0:33:67:0,67,1125 0/0:35,0:35:63:0,63,945 0/0:35,0:35:81:0,81,1215 +20 10622469 . T G 420.56 VQSRTrancheSNP99.95to100.00 HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.393;AN=200;InbreedingCoeff=-0.0053;AF=0.004023;GQ_STDDEV=24.64;FS=289.292;DP=38754;GQ_MEAN=79.3;VQSLOD=-705.5;ClippingRankSum=3.22;BaseQRankSum=-6.497;MLEAF=0.004023;MLEAC=7;MQ=59.69;QD=0.47;MQRankSum=-0.266;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:75:0,75,1125 0/0:37,0:37:93:0,93,1395 0/0:36,0:36:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:41,0:41:90:0,90,1350 0/0:28,0:28:60:0,60,900 0/0:34,0:34:75:0,75,1125 0/0:30,0:30:78:0,78,1215 0/0:40,0:40:96:0,96,1440 0/0:25,0:25:63:0,63,945 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:30,0:30:81:0,81,1215 0/0:33,0:33:66:0,66,990 0/0:25,0:25:72:0,72,1080 0/0:25,0:25:63:0,63,945 0/0:20,0:20:60:0,60,764 0/0:29,0:29:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:47,0:47:99:0,117,1755 0/0:32,0:32:66:0,66,990 0/0:35,0:35:72:0,72,1080 0/0:32,0:32:60:0,60,900 0/0:40,0:40:99:0,99,1485 0/0:50,0:50:99:0,120,1800 0/0:45,0:45:99:0,108,1620 0/0:40,0:40:82:0,82,1305 0/0:34,0:34:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/0:33,0:33:63:0,63,945 0/0:75,0:75:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:31,0:31:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:64,0:64:99:0,120,1800 0/0:65,0:65:76:0,76,1800 0/0:42,0:42:99:0,100,1589 0/0:98,0:98:58:0,58,2727 0/0:35,0:35:72:0,72,1170 0/1:108,42:150:56:56,0,3017 0/0:59,0:59:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:146,0:146:0:0,0,3779 0/0:56,0:56:98:0,98,1800 0/0:48,0:48:99:0,120,1800 0/0:118,26:144:88:0,88,3618 0/0:45,0:45:84:0,84,1575 0/0:110,26:136:95:0,95,3377 0/0:33,0:33:81:0,81,1215 0/0:51,0:51:83:0,83,1800 0/0:45,0:45:99:0,114,1688 0/0:82,0:82:99:0,120,1800 0/0:128,36:164:95:0,95,3863 0/0:66,0:66:83:0,83,1800 0/0:66,0:66:99:0,120,1800 0/0:50,0:50:99:0,105,1575 0/0:121,37:158:14:0,14,3544 0/0:72,0:72:99:0,120,1800 0/0:51,0:51:83:0,83,1800 0/0:45,0:45:99:0,102,1530 0/0:27,0:27:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:141,34:175:88:0,88,4216 0/0:26,0:26:60:0,60,900 0/0:44,0:44:99:0,99,1485 0/0:39,0:39:99:0,101,1530 0/0:39,0:39:84:0,84,1260 0/0:20,0:20:60:0,60,731 0/0:29,0:29:62:0,62,990 0/1:90,35:125:53:53,0,2312 0/0:38,0:38:99:0,99,1485 0/0:33,0:33:60:0,60,900 0/0:40,0:40:69:0,69,1035 0/0:101,22:123:99:0,109,2962 0/0:24,0:24:66:0,66,958 0/0:85,0:85:24:0,24,2319 0/0:27,0:27:60:0,60,900 0/0:41,0:41:64:0,64,1395 0/0:108,0:108:51:0,51,2933 0/0:46,0:46:99:0,113,1755 0/0:29,0:29:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:29,0:29:72:0,72,1080 0/0:81,0:81:99:0,120,1800 0/0:36,0:36:69:0,69,1035 0/0:41,0:41:99:0,102,1530 0/0:30,0:30:68:0,68,1035 0/0:29,0:29:70:0,70,1080 0/0:29,0:29:62:0,62,945 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:33,0:33:67:0,67,1125 0/0:26,0:26:63:0,63,945 0/0:35,0:35:81:0,81,1215 +20 10622501 rs35761929 G C 236882.00 PASS HWP=0.006;AC=11;culprit=QD;MQ0=0;ReadPosRankSum=0.289;AN=200;InbreedingCoeff=0.116;AF=0.061;GQ_STDDEV=654.69;FS=1.281;DP=46588;GQ_MEAN=287.07;POSITIVE_TRAIN_SITE;VQSLOD=5.0;ClippingRankSum=0.149;BaseQRankSum=-3.759;MLEAF=0.061;MLEAC=106;MQ=59.71;QD=14.39;DB;MQRankSum=-0.076;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:75:0,75,1125 0/0:37,0:37:93:0,93,1395 0/0:36,0:36:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:41,0:41:90:0,90,1350 0/0:28,0:28:60:0,60,900 0/0:34,0:34:75:0,75,1125 0/0:30,0:30:78:0,78,1215 0/0:40,0:40:96:0,96,1440 0/0:25,0:25:63:0,63,945 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:30,0:30:81:0,81,1215 0/0:33,0:33:66:0,66,990 0/0:25,0:25:72:0,72,1080 0/0:25,0:25:63:0,63,945 0/0:20,0:20:60:0,60,764 0/0:29,0:29:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/1:64,50:114:99:1291,0,1871 0/0:32,0:32:66:0,66,990 0/0:35,0:35:72:0,72,1080 0/0:32,0:32:60:0,60,900 0/0:40,0:40:99:0,99,1485 0/0:50,0:50:99:0,120,1800 0/0:45,0:45:99:0,108,1620 0/0:40,0:40:82:0,82,1305 0/0:34,0:34:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/0:33,0:33:63:0,63,945 0/1:101,89:190:99:2544,0,3288 0/0:76,0:76:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:31,0:31:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:64,0:64:99:0,120,1800 0/0:65,0:65:76:0,76,1800 0/0:42,0:42:99:0,100,1589 0/0:44,0:44:87:0,87,1305 0/0:35,0:35:72:0,72,1170 0/1:80,65:145:99:1648,0,2493 0/0:59,0:59:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/1:88,70:158:99:1862,0,2915 0/0:78,0:78:99:0,120,1800 0/0:56,0:56:98:0,98,1800 0/0:48,0:48:99:0,120,1800 0/1:63,77:140:99:2227,0,1925 0/0:45,0:45:84:0,84,1575 0/1:77,64:141:99:1633,0,2465 0/0:33,0:33:81:0,81,1215 0/0:51,0:51:83:0,83,1800 0/0:45,0:45:99:0,114,1688 0/0:82,0:82:99:0,120,1800 0/1:87,72:159:99:1858,0,2657 0/0:66,0:66:83:0,83,1800 0/0:66,0:66:99:0,120,1800 0/0:50,0:50:99:0,105,1575 0/1:94,69:163:99:1727,0,3069 0/0:72,0:72:99:0,120,1800 0/0:51,0:51:83:0,83,1800 0/0:45,0:45:99:0,102,1530 0/0:27,0:27:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:110,85:195:99:2289,0,3595 0/0:26,0:26:60:0,60,900 0/0:44,0:44:99:0,99,1485 0/0:39,0:39:99:0,101,1530 0/0:39,0:39:84:0,84,1260 0/0:20,0:20:60:0,60,731 0/0:29,0:29:62:0,62,990 0/0:36,0:36:69:0,69,1035 0/0:38,0:38:99:0,99,1485 0/0:33,0:33:60:0,60,900 0/0:40,0:40:69:0,69,1035 0/1:67,61:128:99:1728,0,2037 0/0:24,0:24:66:0,66,958 0/0:24,0:24:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:41,0:41:64:0,64,1395 0/0:29,0:29:72:0,72,1080 0/0:46,0:46:99:0,113,1755 0/0:29,0:29:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:29,0:29:72:0,72,1080 0/0:81,0:81:99:0,120,1800 0/0:36,0:36:69:0,69,1035 0/1:121,126:247:99:3299,0,3645 0/0:30,0:30:68:0,68,1035 0/0:29,0:29:70:0,70,1080 0/0:29,0:29:62:0,62,945 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:33,0:33:67:0,67,1125 0/0:26,0:26:63:0,63,945 0/0:35,0:35:81:0,81,1215 +20 10623089 rs147841407 C T 1033.95 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=-0.477;AN=200;InbreedingCoeff=-0.0065;AF=0.001724;GQ_STDDEV=27.74;FS=0.0;DP=14791;GQ_MEAN=44.41;POSITIVE_TRAIN_SITE;VQSLOD=4.54;ClippingRankSum=0.06;BaseQRankSum=-2.981;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=15.91;DB;MQRankSum=-0.876;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:14,0:14:33:0,33,508 0/0:13,0:13:39:0,39,497 0/0:14,0:14:25:0,25,522 0/0:15,0:15:42:0,42,552 0/0:20,0:20:54:0,54,810 0/0:21,0:21:60:0,60,900 0/0:16,0:16:42:0,42,630 0/0:15,0:15:42:0,42,630 0/0:22,0:22:57:0,57,855 0/0:10,0:10:19:0,19,332 0/0:23,0:23:60:0,60,900 0/0:9,0:9:24:0,24,338 0/0:11,0:11:33:0,33,426 0/0:12,0:12:36:0,36,442 0/0:6,0:6:0:0,0,145 0/0:11,0:11:33:0,33,381 0/0:7,0:7:21:0,21,256 0/0:4,0:4:9:0,9,135 0/0:8,0:8:21:0,21,301 0/0:7,0:7:21:0,21,258 0/0:7,0:7:21:0,21,237 0/0:11,0:11:30:0,30,450 0/0:3,0:3:9:0,9,105 0/0:28,0:28:75:0,75,1124 0/0:23,0:23:66:0,66,990 0/0:22,0:22:66:0,66,827 0/0:13,0:13:39:0,39,490 0/0:19,0:19:24:0,24,675 0/0:27,0:27:66:0,66,990 0/0:27,0:27:69:0,69,1035 0/0:21,0:21:60:0,60,844 0/0:11,0:11:33:0,33,435 0/0:34,0:34:93:0,93,1395 0/0:41,0:41:90:0,90,1575 0/0:38,0:38:81:0,81,1215 0/0:6,0:6:15:0,15,225 0/0:4,0:4:9:0,9,135 0/0:7,0:7:21:0,21,263 0/0:15,0:15:39:0,39,585 0/0:35,0:35:74:0,74,1260 0/0:12,0:12:36:0,36,468 0/0:18,0:18:45:0,45,675 0/0:22,0:22:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:26,0:26:65:0,65,1080 0/0:24,0:24:72:0,72,911 0/0:29,0:29:69:0,69,1035 0/0:16,0:16:42:0,42,630 0/0:13,0:13:39:0,39,494 0/0:24,0:24:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:22,0:22:61:0,61,809 0/0:11,0:11:33:0,33,390 0/0:20,0:20:57:0,57,855 0/0:14,0:14:32:0,32,483 0/0:27,0:27:63:0,63,945 0/0:28,0:28:75:0,75,1125 0/0:35,0:35:78:0,78,1170 0/0:17,0:17:48:0,48,720 0/0:20,0:20:24:0,24,611 0/0:28,0:28:62:0,62,990 0/0:40,0:40:99:0,99,1485 0/0:21,0:21:60:0,60,900 0/0:26,0:26:64:0,64,917 0/0:8,0:8:11:0,11,259 0/0:6,0:6:18:0,18,243 0/0:8,0:8:24:0,24,313 0/0:26,0:26:60:0,60,900 0/0:11,0:11:33:0,33,435 0/0:23,0:23:63:0,63,945 0/0:10,0:10:27:0,27,405 0/0:13,0:13:38:0,38,494 0/0:12,0:12:36:0,36,444 0/0:13,0:13:21:0,21,495 0/0:7,0:7:21:0,21,274 0/0:12,0:12:33:0,33,482 0/0:20,0:20:51:0,51,765 0/0:13,0:13:39:0,39,481 0/0:8,0:8:24:0,24,304 0/0:9,0:9:27:0,27,332 0/0:9,0:9:27:0,27,353 0/0:11,0:11:27:0,27,405 0/0:17,0:17:51:0,51,682 0/0:12,0:12:29:0,29,485 0/0:30,0:30:69:0,69,1035 0/0:11,0:11:27:0,27,404 0/0:8,0:8:24:0,24,299 0/0:15,0:15:5:0,5,480 0/1:16,16:32:99:493,0,575 0/0:15,0:15:42:0,42,630 0/0:9,0:9:27:0,27,353 0/0:18,0:18:54:0,54,771 0/0:7,0:7:15:0,15,225 0/0:22,0:22:60:0,60,900 0/0:8,0:8:24:0,24,308 0/0:15,0:15:42:0,42,630 0/0:16,0:16:42:0,42,630 0/0:10,0:10:27:0,27,381 0/0:14,0:14:39:0,39,574 +20 10624386 . G A 146.76 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=1.59;AN=200;InbreedingCoeff=-0.0037;AF=5.747E-4;GQ_STDDEV=18.36;FS=0.0;DP=14719;GQ_MEAN=43.25;VQSLOD=4.84;ClippingRankSum=-1.067;BaseQRankSum=1.07;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=18.35;MQRankSum=0.572;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,800 0/0:10,0:10:30:0,30,383 0/0:21,0:21:60:0,60,827 0/0:8,0:8:24:0,24,306 0/0:21,0:21:60:0,60,900 0/0:14,0:14:39:0,39,585 0/0:21,0:21:60:0,60,900 0/0:15,0:15:42:0,42,562 0/0:22,0:22:60:0,60,900 0/0:15,0:15:42:0,42,570 0/0:10,0:10:30:0,30,385 0/0:13,0:13:2:0,2,373 0/0:11,0:11:33:0,33,424 0/0:9,0:9:27:0,27,337 0/0:9,0:9:21:0,21,308 0/0:8,0:8:21:0,21,301 0/0:11,0:11:27:0,27,395 0/0:13,0:13:33:0,33,460 0/0:20,0:20:60:0,60,688 0/0:9,0:9:27:0,27,331 0/0:10,0:10:27:0,27,371 0/0:10,0:10:30:0,30,381 0/0:9,0:9:21:0,21,315 0/0:14,0:14:39:0,39,585 0/0:14,0:14:39:0,39,544 0/0:25,0:25:63:0,63,882 0/0:16,0:16:39:0,39,585 0/0:21,0:21:51:0,51,669 0/0:21,0:21:60:0,60,663 0/0:20,0:20:60:0,60,704 0/0:7,0:7:21:0,21,237 0/0:21,0:21:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:36,0:36:93:0,93,1395 0/0:30,0:30:66:0,66,990 0/0:20,0:20:60:0,60,755 0/0:15,0:15:39:0,39,555 0/0:9,0:9:24:0,24,319 0/0:13,0:13:33:0,33,495 0/0:9,0:9:24:0,24,360 0/0:18,0:18:51:0,51,609 0/0:28,0:28:66:0,66,990 0/0:9,0:9:21:0,21,315 0/0:19,0:19:36:0,36,675 0/0:14,0:14:42:0,42,528 0/0:19,0:19:48:0,48,720 0/0:22,0:22:60:0,60,796 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:28,0:28:62:0,62,945 0/0:21,0:21:60:0,60,900 0/0:15,0:15:42:0,42,630 0/0:21,0:21:60:0,60,895 0/0:7,0:7:21:0,21,250 0/0:10,0:10:27:0,27,405 0/0:15,0:15:42:0,42,630 0/0:16,0:16:39:0,39,567 0/0:21,0:21:34:0,34,652 0/0:19,0:19:25:0,25,638 0/0:18,0:18:48:0,48,720 0/0:13,0:13:33:0,33,495 0/0:16,0:16:37:0,37,578 0/0:27,0:27:60:0,60,900 0/0:16,0:16:39:0,39,585 0/0:15,0:15:37:0,37,523 0/0:7,0:7:21:0,21,247 0/0:8,0:8:21:0,21,294 0/0:5,0:5:12:0,12,180 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,291 0/0:15,0:15:39:0,39,532 0/0:4,0:4:9:0,9,135 0/0:11,0:11:33:0,33,393 0/1:2,6:8:46:197,0,46 0/0:14,0:14:33:0,33,495 0/0:5,0:5:15:0,15,186 0/0:8,0:8:21:0,21,268 0/0:9,0:9:24:0,24,336 0/0:7,0:7:21:0,21,254 0/0:12,0:12:33:0,33,433 0/0:12,0:12:0:0,0,347 0/0:10,0:10:27:0,27,364 0/0:13,0:13:36:0,36,528 0/0:9,0:9:24:0,24,360 0/0:10,0:10:27:0,27,385 0/0:9,0:9:27:0,27,330 0/0:21,0:21:60:0,60,781 0/0:20,0:20:60:0,60,740 0/0:14,0:14:36:0,36,540 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,769 0/0:8,0:8:21:0,21,315 0/0:5,0:5:15:0,15,175 0/0:23,0:23:66:0,66,990 0/0:15,0:15:29:0,29,570 0/0:8,0:8:21:0,21,315 0/0:11,0:11:33:0,33,400 0/0:3,0:3:9:0,9,112 0/0:12,0:12:30:0,30,450 +20 10624396 rs2273059 T C 13476.30 PASS HWP=1.0;AC=4;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.664;AN=200;InbreedingCoeff=-0.0254;AF=0.023;GQ_STDDEV=58.98;FS=0.0;DP=16610;GQ_MEAN=60.0;POSITIVE_TRAIN_SITE;VQSLOD=5.51;ClippingRankSum=0.052;BaseQRankSum=2.28;MLEAF=0.023;MLEAC=40;MQ=60.0;QD=13.78;DB;MQRankSum=-0.077;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,882 0/0:21,0:21:60:0,60,827 0/1:9,4:13:99:121,0,293 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:15,0:15:42:0,42,562 0/0:25,0:25:69:0,69,1035 0/1:16,8:24:99:239,0,512 0/0:21,0:21:60:0,60,752 0/0:11,0:11:30:0,30,450 0/0:11,0:11:33:0,33,424 0/0:9,0:9:27:0,27,337 0/0:7,0:7:15:0,15,225 0/0:8,0:8:21:0,21,301 0/0:18,0:18:51:0,51,765 0/0:24,0:24:60:0,60,900 0/0:22,0:22:57:0,57,855 0/0:20,0:20:60:0,60,732 0/0:10,0:10:27:0,27,371 0/0:10,0:10:30:0,30,381 0/0:11,0:11:30:0,30,450 0/0:20,0:20:60:0,60,750 0/0:25,0:25:60:0,60,900 0/0:25,0:25:63:0,63,882 0/0:16,0:16:39:0,39,585 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,663 0/0:20,0:20:60:0,60,704 0/0:7,0:7:21:0,21,237 0/0:23,0:23:60:0,60,900 0/0:28,0:28:63:0,63,945 0/1:27,15:42:99:427,0,849 0/0:30,0:30:66:0,66,990 0/0:30,0:30:87:0,87,1305 0/0:20,0:20:60:0,60,714 0/0:9,0:9:24:0,24,319 0/0:13,0:13:33:0,33,495 0/0:9,0:9:24:0,24,360 0/0:21,0:21:60:0,60,728 0/0:28,0:28:66:0,66,990 0/0:9,0:9:21:0,21,315 0/0:21,0:21:57:0,57,855 0/0:14,0:14:42:0,42,528 0/0:22,0:22:63:0,63,814 0/0:22,0:22:60:0,60,796 0/1:13,11:24:99:328,0,371 0/0:31,0:31:87:0,87,1305 0/0:28,0:28:62:0,62,945 0/0:21,0:21:60:0,60,900 0/0:15,0:15:42:0,42,630 0/0:21,0:21:60:0,60,895 0/0:11,0:11:30:0,30,396 0/0:15,0:15:42:0,42,630 0/0:21,0:21:60:0,60,700 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:20,0:20:60:0,60,785 0/0:20,0:20:60:0,60,640 0/0:16,0:16:37:0,37,578 0/0:27,0:27:60:0,60,900 0/0:16,0:16:39:0,39,585 0/0:15,0:15:37:0,37,523 0/0:7,0:7:21:0,21,247 0/0:8,0:8:21:0,21,294 0/0:5,0:5:12:0,12,180 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,291 0/0:15,0:15:39:0,39,532 0/0:6,0:6:15:0,15,218 0/0:11,0:11:33:0,33,393 0/0:8,0:8:22:0,22,288 0/0:14,0:14:33:0,33,495 0/0:7,0:7:21:0,21,267 0/0:8,0:8:21:0,21,268 0/0:9,0:9:24:0,24,336 0/0:7,0:7:21:0,21,254 0/0:12,0:12:33:0,33,433 0/0:10,0:10:21:0,21,315 0/0:10,0:10:27:0,27,364 0/0:13,0:13:36:0,36,528 0/0:9,0:9:24:0,24,360 0/0:10,0:10:27:0,27,385 0/0:21,0:21:63:0,63,726 0/0:21,0:21:60:0,60,781 0/0:20,0:20:60:0,60,740 0/0:21,0:21:60:0,60,764 0/0:28,0:28:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,769 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,254 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,842 0/0:8,0:8:21:0,21,315 0/0:11,0:11:33:0,33,400 0/0:7,0:7:21:0,21,265 0/0:12,0:12:30:0,30,450 +20 10624398 rs77308315 G A 1073.75 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=-0.133;AN=200;InbreedingCoeff=-0.0033;AF=0.001724;GQ_STDDEV=27.13;FS=4.499;DP=16739;GQ_MEAN=51.02;POSITIVE_TRAIN_SITE;VQSLOD=2.89;ClippingRankSum=1.07;BaseQRankSum=-2.933;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=12.63;DB;MQRankSum=-1.2;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:23:0,23,817 0/0:21,0:21:60:0,60,882 0/0:21,0:21:60:0,60,827 0/0:13,0:13:27:0,27,405 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,706 0/0:27,0:27:55:0,55,1090 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,752 0/0:11,0:11:30:0,30,450 0/0:11,0:11:33:0,33,424 0/0:9,0:9:27:0,27,337 0/0:7,0:7:15:0,15,225 0/0:8,0:8:21:0,21,301 0/0:21,0:21:60:0,60,768 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,732 0/0:10,0:10:27:0,27,371 0/0:10,0:10:30:0,30,381 0/0:11,0:11:30:0,30,450 0/0:20,0:20:60:0,60,750 0/0:25,0:25:60:0,60,900 0/0:25,0:25:63:0,63,882 0/0:22,0:22:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,663 0/0:20,0:20:60:0,60,704 0/0:7,0:7:21:0,21,237 0/0:23,0:23:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:39,0:39:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:30,0:30:87:0,87,1305 0/0:20,0:20:60:0,60,714 0/0:9,0:9:24:0,24,319 0/0:13,0:13:33:0,33,495 0/0:9,0:9:24:0,24,360 0/0:21,0:21:60:0,60,728 0/0:28,0:28:66:0,66,990 0/0:18,0:18:14:0,14,596 0/0:21,0:21:57:0,57,855 0/0:14,0:14:42:0,42,528 0/0:22,0:22:63:0,63,814 0/0:22,0:22:60:0,60,796 0/0:24,0:24:63:0,63,945 0/1:15,17:32:99:458,0,529 0/0:28,0:28:62:0,62,945 0/0:21,0:21:60:0,60,900 0/0:15,0:15:42:0,42,630 0/0:21,0:21:60:0,60,895 0/0:11,0:11:30:0,30,396 0/0:15,0:15:42:0,42,630 0/0:21,0:21:60:0,60,700 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:20,0:20:60:0,60,785 0/0:20,0:20:60:0,60,640 0/0:16,0:16:37:0,37,578 0/0:27,0:27:60:0,60,900 0/0:16,0:16:39:0,39,585 0/0:15,0:15:37:0,37,523 0/0:7,0:7:21:0,21,247 0/0:8,0:8:21:0,21,294 0/0:7,0:7:21:0,21,263 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,291 0/0:15,0:15:39:0,39,532 0/0:6,0:6:15:0,15,218 0/0:11,0:11:33:0,33,393 0/0:8,0:8:22:0,22,288 0/0:14,0:14:33:0,33,495 0/0:7,0:7:21:0,21,267 0/0:8,0:8:21:0,21,268 0/0:9,0:9:24:0,24,336 0/0:7,0:7:21:0,21,254 0/0:12,0:12:33:0,33,433 0/0:10,0:10:21:0,21,315 0/0:10,0:10:27:0,27,364 0/0:13,0:13:36:0,36,528 0/0:9,0:9:24:0,24,360 0/0:10,0:10:27:0,27,385 0/0:21,0:21:63:0,63,726 0/0:21,0:21:60:0,60,781 0/0:20,0:20:60:0,60,740 0/0:21,0:21:60:0,60,764 0/0:28,0:28:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,769 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,254 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,842 0/0:8,0:8:21:0,21,315 0/0:11,0:11:33:0,33,400 0/0:7,0:7:21:0,21,265 0/0:12,0:12:30:0,30,450 +20 10624502 rs56225585 G A 112945.00 PASS HWP=0.0;AC=6;culprit=MQ;MQ0=0;ReadPosRankSum=0.299;AN=200;InbreedingCoeff=0.2578;AF=0.123;GQ_STDDEV=186.11;FS=0.0;DP=21631;GQ_MEAN=120.84;POSITIVE_TRAIN_SITE;VQSLOD=4.78;ClippingRankSum=0.217;BaseQRankSum=-1.466;MLEAF=0.124;MLEAC=215;MQ=60.0;QD=16.31;DB;MQRankSum=0.311;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:67:0,67,987 0/0:21,0:21:60:0,60,882 0/0:21,0:21:60:0,60,827 0/0:30,0:30:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:33,0:33:58:0,58,1127 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:63:0,63,945 1/1:0,13:13:39:447,39,0 0/0:10,0:10:24:0,24,360 0/1:11,12:23:99:325,0,324 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,732 0/0:21,0:21:60:0,60,900 0/0:24,0:24:61:0,61,843 0/0:12,0:12:30:0,30,450 0/0:30,0:30:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:9,0:9:21:0,21,315 0/0:23,0:23:63:0,63,890 0/0:21,0:21:60:0,60,663 0/0:27,0:27:69:0,69,1035 0/0:20,0:20:60:0,60,722 0/0:23,0:23:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:39,0:39:60:0,60,900 0/0:30,0:30:66:0,66,990 0/1:29,25:54:99:613,0,735 1/1:0,64:64:99:2065,192,0 0/0:21,0:21:60:0,60,860 0/0:23,0:23:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:25,0:25:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:10,0:10:21:0,21,315 0/0:24,0:24:63:0,63,868 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,814 0/0:22,0:22:60:0,60,796 0/0:22,0:22:60:0,60,869 0/0:28,0:28:63:0,63,945 0/0:28,0:28:62:0,62,945 0/0:24,0:24:62:0,62,817 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,895 0/0:10,0:10:21:0,21,315 0/0:19,0:19:42:0,42,630 0/0:8,0:8:21:0,21,258 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:29,0:29:75:0,75,1125 0/0:20,0:20:60:0,60,785 0/0:22,0:22:60:0,60,802 0/0:22,0:22:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:9,0:9:21:0,21,308 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,302 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,291 0/0:22,0:22:60:0,60,809 0/0:11,0:11:21:0,21,315 0/0:24,0:24:60:0,60,869 0/0:9,0:9:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:4,0:4:12:0,12,135 0/0:23,0:23:60:0,60,846 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:27,0:27:63:0,63,945 0/0:10,0:10:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:9,0:9:24:0,24,360 0/0:10,0:10:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,781 0/0:20,0:20:60:0,60,740 0/0:21,0:21:60:0,60,764 0/0:28,0:28:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,769 0/0:22,0:22:60:0,60,900 0/0:14,0:14:1:0,1,428 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,842 0/0:8,0:8:21:0,21,315 0/0:14,0:14:30:0,30,450 0/0:14,0:14:24:0,24,360 0/0:22,0:22:60:0,60,797 +20 10625603 . T G 40.80 VQSRTrancheSNP99.95to100.00 HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=-6.832;AN=200;InbreedingCoeff=-0.0038;AF=5.747E-4;GQ_STDDEV=19.79;FS=280.223;DP=72280;GQ_MEAN=113.59;VQSLOD=-655.9;ClippingRankSum=8.01;BaseQRankSum=-3.354;MLEAF=5.747E-4;MLEAC=1;MQ=60.99;QD=0.19;MQRankSum=4.59;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:57,0:57:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:41,0:41:99:0,117,1755 0/0:32,0:32:61:0,61,1146 0/0:32,0:32:78:0,78,1170 0/0:44,0:44:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:42,0:42:99:0,114,1710 0/0:53,0:53:99:0,120,1800 0/0:124,0:124:70:0,70,1800 0/1:167,44:211:91:91,0,5052 0/0:78,0:78:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:85,0:85:61:0,61,1800 0/0:107,0:107:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:129,0:129:99:0,120,1800 0/0:151,0:151:99:0,115,1800 0/0:107,0:107:99:0,120,1800 0/0:41,0:41:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:73,0:73:86:0,86,1800 0/0:73,0:73:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:129,0:129:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:176,0:176:0:0,0,5124 0/0:64,0:64:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:76,0:76:82:0,82,1800 0/0:144,0:144:60:0,60,4341 0/0:80,0:80:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:114,0:114:99:0,120,1800 0/0:128,0:128:99:0,120,1800 0/0:102,0:102:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:158,0:158:0:0,0,4526 0/0:163,0:163:99:0,101,1800 0/0:152,0:152:0:0,0,4269 0/0:92,0:92:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:35,0:35:99:0,105,1354 0/0:40,0:40:99:0,105,1575 0/0:105,0:105:99:0,120,1800 0/0:36,0:36:87:0,87,1305 0/0:79,0:79:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:37,0:37:99:0,105,1575 0/0:50,0:50:99:0,104,1800 0/0:71,0:71:99:0,120,1800 0/0:48,0:48:61:0,61,1800 0/0:39,0:39:99:0,108,1620 0/0:33,0:33:93:0,93,1395 0/0:41,0:41:99:0,117,1755 0/0:41,0:41:99:0,117,1755 0/0:65,0:65:99:0,120,1800 0/0:60,0:60:97:0,97,1800 0/0:78,0:78:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:158,0:158:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:35,0:35:99:0,99,1479 0/0:86,0:86:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:39,0:39:99:0,111,1665 0/0:62,0:62:99:0,120,1800 0/0:48,0:48:99:0,108,1620 0/0:54,0:54:99:0,106,1800 +20 10625774 rs115449289 G A 18150.50 PASS HWP=1.0;AC=4;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.66;AN=200;InbreedingCoeff=-0.0116;AF=0.011;GQ_STDDEV=110.23;FS=1.137;DP=43962;GQ_MEAN=110.32;POSITIVE_TRAIN_SITE;VQSLOD=4.56;ClippingRankSum=-0.195;BaseQRankSum=1.39;MLEAF=0.011;MLEAC=20;MQ=60.0;QD=14.38;DB;MQRankSum=0.43;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:27,0:27:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:46,0:46:99:0,120,1800 0/0:32,0:32:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:57,0:57:99:0,120,1800 0/0:37,0:37:72:0,72,1080 0/0:64,0:64:99:0,120,1800 0/0:44,0:44:99:0,120,1692 0/0:62,0:62:99:0,120,1800 0/0:24,0:24:63:0,63,945 0/0:56,0:56:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:30,0:30:75:0,75,1094 0/0:27,0:27:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:43,0:43:72:0,72,1575 0/1:43,29:72:99:850,0,1262 0/1:32,20:52:99:542,0,993 0/0:54,0:54:99:0,120,1800 0/0:22,0:22:60:0,60,900 0/0:41,0:41:96:0,96,1440 0/0:55,0:55:99:0,120,1800 0/1:26,36:62:99:1080,0,688 0/0:67,0:67:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/1:37,55:92:99:1640,0,1055 0/0:83,0:83:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:31,0:31:75:0,75,1125 0/0:51,0:51:99:0,120,1800 0/0:37,0:37:69:0,69,1080 0/0:52,0:52:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:54,0:54:99:0,105,1575 0/0:59,0:59:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:35,0:35:73:0,73,1305 0/0:52,0:52:99:0,120,1800 0/0:47,0:47:99:0,102,1530 0/0:96,0:96:99:0,120,1800 0/0:114,0:114:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:71,0:71:99:0,120,1800 0/0:111,0:111:99:0,120,1800 0/0:63,0:63:99:0,99,1485 0/0:68,0:68:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:27,0:27:64:0,64,1035 0/0:30,0:30:66:0,66,990 0/0:101,0:101:99:0,120,1800 0/0:34,0:34:81:0,81,1215 0/0:53,0:53:99:0,119,1800 0/0:43,0:43:97:0,97,1485 0/0:65,0:65:99:0,120,1800 0/0:42,0:42:99:0,111,1633 0/0:45,0:45:99:0,102,1572 0/0:27,0:27:66:0,66,1035 0/0:44,0:44:99:0,102,1600 0/0:35,0:35:71:0,71,1350 0/0:38,0:38:82:0,82,1395 0/0:35,0:35:90:0,90,1350 0/0:22,0:22:60:0,60,900 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:75:0,75,1020 0/0:31,0:31:65:0,65,990 0/0:30,0:30:68:0,68,1035 0/0:64,0:64:99:0,120,1800 0/0:38,0:38:96:0,96,1440 0/0:43,0:43:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:47,0:47:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/0:29,0:29:63:0,63,1080 0/0:28,0:28:69:0,69,1035 0/0:37,0:37:99:0,105,1575 0/0:35,0:35:87:0,87,1305 0/0:29,0:29:69:0,69,1035 0/0:29,0:29:75:0,75,1125 0/0:28,0:28:72:0,72,1080 0/0:34,0:34:84:0,84,1260 +20 10625804 rs1801140 T G 194773.00 PASS HWP=0.066;AC=18;culprit=FS;MQ0=0;ReadPosRankSum=0.377;AN=200;InbreedingCoeff=0.0705;AF=0.103;GQ_STDDEV=361.16;FS=0.0;DP=46720;GQ_MEAN=242.26;POSITIVE_TRAIN_SITE;VQSLOD=6.8;ClippingRankSum=-0.134;BaseQRankSum=3.11;MLEAF=0.103;MLEAC=180;MQ=59.59;QD=15.91;DB;MQRankSum=0.111;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:27,0:27:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/1:38,33:71:99:1017,0,1045 0/0:32,0:32:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:57,0:57:99:0,120,1800 0/0:37,0:37:72:0,72,1080 0/0:64,0:64:99:0,120,1800 0/1:30,51:81:99:1450,0,820 0/0:62,0:62:99:0,120,1800 0/0:24,0:24:63:0,63,945 0/0:56,0:56:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:30,0:30:75:0,75,1094 0/0:27,0:27:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:43,0:43:72:0,72,1575 0/0:27,0:27:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/1:37,28:65:99:770,0,1026 0/0:22,0:22:60:0,60,900 0/0:41,0:41:96:0,96,1440 0/0:55,0:55:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:49,49:98:99:1646,0,1355 0/1:65,61:126:99:2117,0,1974 0/0:106,0:106:99:0,120,1800 0/0:31,0:31:75:0,75,1125 0/0:51,0:51:99:0,120,1800 0/0:37,0:37:69:0,69,1080 0/0:52,0:52:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:54,0:54:99:0,105,1575 0/0:59,0:59:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:33,38:71:99:1256,0,973 0/0:60,0:60:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/1:44,40:84:99:1315,0,1308 0/1:42,50:92:99:1601,0,1166 0/1:52,44:96:99:1439,0,1616 0/0:84,0:84:99:0,120,1800 0/1:44,38:82:99:1207,0,1312 0/0:61,0:61:99:0,120,1800 0/1:37,23:60:99:640,0,1170 0/0:35,0:35:73:0,73,1305 0/0:52,0:52:99:0,120,1800 0/0:47,0:47:99:0,102,1530 0/1:56,45:101:99:1311,0,1642 0/1:60,50:110:99:1556,0,1796 0/0:69,0:69:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/1:38,26:64:99:796,0,1153 0/0:111,0:111:99:0,120,1800 0/0:63,0:63:99:0,99,1485 0/0:68,0:68:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:27,0:27:64:0,64,1035 0/0:30,0:30:66:0,66,990 0/1:51,64:115:99:2163,0,1532 0/0:34,0:34:81:0,81,1215 0/0:53,0:53:99:0,119,1800 0/0:43,0:43:97:0,97,1485 0/0:65,0:65:99:0,120,1800 0/0:42,0:42:99:0,111,1633 0/0:45,0:45:99:0,102,1572 0/0:27,0:27:66:0,66,1035 0/0:44,0:44:99:0,102,1600 0/0:35,0:35:71:0,71,1350 0/0:38,0:38:82:0,82,1395 0/1:22,26:48:99:846,0,623 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,1035 0/1:20,19:39:99:626,0,612 0/0:31,0:31:65:0,65,990 0/0:30,0:30:68:0,68,1035 0/0:64,0:64:99:0,120,1800 0/0:38,0:38:96:0,96,1440 0/0:43,0:43:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:47,0:47:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/0:29,0:29:63:0,63,1080 0/0:28,0:28:69:0,69,1035 0/0:37,0:37:99:0,105,1575 0/1:48,33:81:99:914,0,1234 0/0:29,0:29:69:0,69,1035 0/0:29,0:29:75:0,75,1125 0/0:28,0:28:72:0,72,1080 0/0:34,0:34:84:0,84,1260 +20 10626007 . AGTGGCAGGTCTTTCCTTTCCACCCATTTTTACAGTCACAGTAGAAGTCATTGACCAGGTCGCGACACGTGCCCCCATT A 18515.30 VQSRTrancheINDEL99.95to100.00 HWP=0.0026;AC=27;culprit=FS;MQ0=0;ReadPosRankSum=-5.007;AN=200;InbreedingCoeff=-0.0921;AF=0.084;GQ_STDDEV=51.21;FS=264.203;DP=83126;GQ_MEAN=96.26;VQSLOD=-133.7;ClippingRankSum=7.43;BaseQRankSum=1.64;MLEAF=0.082;MLEAC=143;MQ=58.2;QD=0.02;MQRankSum=0.198;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:27,0:27:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:29,0:29:60:0,60,900 0/0:32,0:32:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:57,0:57:99:0,120,1800 0/0:37,0:37:72:0,72,1080 0/0:64,0:64:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:62,0:62:99:0,120,1800 0/0:24,0:24:63:0,63,945 0/0:56,0:56:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:30,0:30:75:0,75,1094 0/0:27,0:27:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:43,0:43:72:0,72,1575 0/0:27,0:27:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:42,0:42:99:0,105,1575 0/0:22,0:22:60:0,60,900 0/0:41,0:41:96:0,96,1440 0/0:55,0:55:99:0,120,1800 0/0:179,76:255:41:0,41,80774 0/1:184,101:285:99:114,0,83984 0/0:77,0:77:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:287,129:416:83:83,0,123516 0/0:117,0:117:99:0,120,1800 0/0:286,120:406:48:0,48,120229 0/0:31,0:31:75:0,75,1125 0/0:51,0:51:99:0,120,1800 0/0:37,0:37:69:0,69,1080 0/0:52,0:52:99:0,120,1800 0/1:215,89:304:12:12,0,89432 0/1:144,61:205:99:326,0,63828 0/0:59,0:59:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:180,94:274:67:67,0,71201 0/1:175,84:259:44:44,0,73717 0/1:216,80:296:99:175,0,92621 0/0:198,90:288:72:0,72,80896 0/1:182,72:254:99:223,0,77010 0/0:209,100:309:15:0,15,97791 0/0:84,0:84:99:0,120,1800 0/1:187,87:274:99:140,0,81494 0/1:158,69:227:18:18,0,68066 0/1:133,59:192:99:183,0,59527 0/0:35,0:35:73:0,73,1305 0/0:52,0:52:99:0,120,1800 0/1:174,83:257:52:52,0,74169 0/0:89,0:89:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/1:201,90:291:99:136,0,85654 0/0:91,0:91:99:0,120,1800 0/1:154,67:221:59:59,0,71381 0/1:166,87:253:99:331,0,73041 0/0:111,0:111:99:0,120,1800 0/1:186,85:271:73:73,0,76140 0/0:68,0:68:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:27,0:27:72:0,72,1080 0/0:60,0:60:51:0,51,765 0/1:220,117:337:99:298,0,96621 0/0:32,0:32:78:0,78,1170 0/0:53,0:53:99:0,119,1800 0/0:43,0:43:97:0,97,1485 0/1:240,111:351:36:36,0,100857 0/1:136,64:200:99:184,0,60213 0/0:45,0:45:99:0,102,1572 0/1:92,46:138:5:5,0,41362 0/0:44,0:44:99:0,102,1600 0/0:35,0:35:71:0,71,1350 0/1:117,61:178:99:106,0,50811 0/1:129,62:191:31:31,0,60812 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,1035 0/0:35,0:35:84:0,84,1260 0/0:31,0:31:65:0,65,990 0/1:120,56:176:99:169,0,53922 0/0:64,0:64:99:0,120,1800 0/0:38,0:38:96:0,96,1440 0/0:43,0:43:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/1:299,151:450:99:239,0,126750 0/0:47,0:47:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/0:29,0:29:63:0,63,1080 0/1:106,13:119:99:126,0,47591 0/0:37,0:37:99:0,105,1575 0/0:51,0:51:99:0,102,1530 0/0:29,0:29:69:0,69,1035 0/0:29,0:29:75:0,75,1125 0/1:96,51:147:99:268,0,42351 0/1:128,65:193:39:39,0,55097 +20 10626016 rs79176844 T G 40212.40 VQSRTrancheSNP99.95to100.00 HWP=0.0;AC=14;culprit=FS;MQ0=0;ReadPosRankSum=2.26;AN=138;InbreedingCoeff=-0.3123;AF=0.191;GQ_STDDEV=97.41;FS=210.183;DP=56831;GQ_MEAN=86.54;VQSLOD=-445.1;ClippingRankSum=0.356;BaseQRankSum=-5.453;MLEAF=0.225;MLEAC=309;MQ=59.25;QD=1.18;DB;MQRankSum=0.27;CCC=1376;NCC=182 GT:AD:DP:GQ:PL 0/0:27,0:27:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:29,0:29:60:0,60,900 0/0:32,0:32:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:114,0:114:31:0,31,2992 0/0:37,0:37:72:0,72,1080 0/1:117,42:159:1:1,0,3156 0/0:29,0:29:66:0,66,990 0/1:75,29:104:33:33,0,2107 0/0:24,0:24:63:0,63,945 0/1:99,32:131:80:80,0,2723 0/0:33,0:33:75:0,75,1125 0/0:30,0:30:75:0,75,1094 0/0:27,0:27:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:58,0:58:29:0,29,1415 0/0:27,0:27:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:82,0:82:30:0,30,1990 0/0:22,0:22:60:0,60,900 0/0:161,0:161:0:0,0,3431 0/0:154,0:154:0:0,0,3600 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:81,0:81:0:0,0,2145 0/1:91,42:133:99:502,0,2207 0/0:86,19:105:33:0,33,2411 0/1:98,36:134:99:112,0,2345 0/1:101,64:165:99:410,0,2333 ./.:0,0:.:.:. 0/0:53,0:53:78:0,78,1170 ./.:0,0:.:.:. 0/1:93,34:127:99:143,0,2258 0/1:94,50:144:99:201,0,2216 0/0:37,0:37:69:0,69,1080 0/0:63,0:63:0:0,0,1703 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:71,0:71:0:0,0,1867 0/0:75,0:75:0:0,0,1357 ./.:0,0:.:.:. ./.:0,0:.:.:. ./.:0,0:.:.:. ./.:0,0:.:.:. ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:94,0:94:0:0,0,1883 ./.:0,0:.:.:. ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:58,0:58:0:0,0,981 0/0:79,0:79:0:0,0,2234 ./.:0,0:.:.:. 0/0:74,0:74:0:0,0,2091 0/0:96,0:96:0:0,0,2191 ./.:0,0:.:.:. 0/0:77,0:77:0:0,0,1698 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:124,0:124:0:0,0,2478 ./.:0,0:.:.:. 0/0:62,0:62:0:0,0,1716 0/0:25,0:25:63:0,63,945 0/0:43,0:43:0:0,0,1241 0/0:33,0:33:0:0,0,743 ./.:0,0:.:.:. 0/1:38,8:46:40:40,0,4546 0/0:65,0:65:0:0,0,1545 0/0:55,0:55:0:0,0,1324 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:54,0:54:0:0,0,1459 ./.:0,0:.:.:. 0/0:64,0:64:0:0,0,1759 0/0:62,0:62:0:0,0,1523 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:44,0:44:0:0,0,1052 0/0:43,0:43:0:0,0,1182 0/0:36,0:36:47:0,47,1169 0/0:67,0:67:0:0,0,1797 ./.:0,0:.:.:. 0/0:91,0:91:0:0,0,2261 0/1:96,53:149:99:233,0,2210 0/1:93,49:142:99:184,0,2206 0/0:74,0:74:47:0,47,1913 ./.:0,0:.:.:. 0/0:133,40:173:33:0,33,3207 0/1:109,42:151:99:112,0,2506 0/0:57,0:57:0:0,0,1265 ./.:0,0:.:.:. 0/1:101,53:154:99:204,0,2437 0/1:90,43:133:99:166,0,1953 0/0:29,0:29:60:0,60,900 0/0:49,0:49:0:0,0,1292 ./.:0,0:.:.:. ./.:0,0:.:.:. +20 10626633 . G GC 547.71 VQSRTrancheINDEL99.50to99.90 NEGATIVE_TRAIN_SITE;HWP=1.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=-2.374;AN=200;InbreedingCoeff=-0.0;AF=0.001149;GQ_STDDEV=20.23;FS=21.851;DP=29939;GQ_MEAN=69.49;VQSLOD=-3.996;ClippingRankSum=0.791;BaseQRankSum=-2.646;MLEAF=0.001149;MLEAC=2;MQ=59.65;QD=1.71;MQRankSum=-0.064;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:30,0:30:61:0,61,1035 0/0:23,0:23:60:0,60,900 0/0:32,0:32:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:27,0:27:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:31,0:31:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:35,0:35:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:45,0:45:63:0,63,945 0/0:46,0:46:69:0,69,1035 0/0:33,0:33:63:0,63,945 0/0:30,0:30:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:28,0:28:66:0,66,990 0/0:36,0:36:81:0,81,1215 0/0:26,0:26:60:0,60,900 0/0:37,0:37:69:0,69,1035 0/0:87,0:87:99:0,120,1800 0/0:38,0:38:66:0,66,990 0/0:45,0:45:69:0,69,1035 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:41,0:41:69:0,69,1035 0/0:38,0:38:63:0,63,945 0/0:58,0:58:99:0,120,1800 0/0:29,0:29:65:0,65,990 0/0:35,0:35:72:0,72,1080 0/0:27,0:27:64:0,64,739 0/0:31,0:31:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:32,0:32:60:0,60,900 0/1:96,0:98:34:34,0,4405 0/0:35,0:35:69:0,69,1035 0/0:40,0:40:66:0,66,990 0/0:32,0:32:61:0,61,990 0/0:43,0:43:90:0,90,1350 0/0:52,0:52:99:0,114,1710 0/0:31,0:31:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:40,0:40:66:0,66,990 0/0:32,0:32:66:0,66,990 0/0:68,0:68:99:0,120,1800 0/0:42,0:42:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:65,0:65:99:0,120,1800 0/0:43,0:43:60:0,60,900 0/0:34,0:34:63:0,63,945 0/0:37,0:37:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:42,0:42:96:0,96,1440 0/0:35,0:35:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:26,0:26:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:34,0:34:78:0,78,1170 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:43,0:43:86:0,86,1597 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:39,0:39:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:46,0:46:93:0,93,1395 0/0:30,0:30:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:36,0:36:63:0,63,945 0/0:31,0:31:72:0,72,1080 +20 10626639 . T C 2076.08 VQSRTrancheSNP99.95to100.00 HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=-4.054;AN=200;InbreedingCoeff=-0.0155;AF=0.007471;GQ_STDDEV=23.76;FS=167.861;DP=31201;GQ_MEAN=63.36;VQSLOD=-243.1;ClippingRankSum=4.51;BaseQRankSum=-5.803;MLEAF=0.007471;MLEAC=13;MQ=59.37;QD=1.32;MQRankSum=0.106;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:30,0:30:61:0,61,1035 0/0:23,0:23:60:0,60,900 0/0:32,0:32:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:27,0:27:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:31,0:31:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:35,0:35:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:45,0:45:63:0,63,945 0/0:46,0:46:69:0,69,1035 0/0:33,0:33:63:0,63,945 0/0:30,0:30:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:28,0:28:66:0,66,990 0/0:36,0:36:81:0,81,1215 0/0:26,0:26:60:0,60,900 0/0:37,0:37:69:0,69,1035 0/1:97,36:133:99:139,0,2623 0/0:38,0:38:66:0,66,990 0/0:45,0:45:69:0,69,1035 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:41,0:41:69:0,69,1035 0/0:38,0:38:63:0,63,945 0/0:62,0:62:38:0,38,1609 0/0:29,0:29:65:0,65,990 0/0:35,0:35:72:0,72,1080 0/0:27,0:27:64:0,64,739 0/0:31,0:31:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:32,0:32:60:0,60,900 0/1:100,25:125:34:34,0,4405 0/0:35,0:35:69:0,69,1035 0/0:40,0:40:66:0,66,990 0/0:32,0:32:61:0,61,990 0/0:43,0:43:90:0,90,1350 0/0:63,0:63:0:0,0,1501 0/0:31,0:31:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:40,0:40:66:0,66,990 0/0:32,0:32:66:0,66,990 0/0:64,0:64:0:0,0,1447 0/0:42,0:42:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:91,0:91:0:0,0,2059 0/0:43,0:43:60:0,60,900 0/0:34,0:34:63:0,63,945 0/0:37,0:37:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:42,0:42:14:0,14,1025 0/0:35,0:35:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:26,0:26:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:34,0:34:78:0,78,1170 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:69,0:69:22:0,22,1781 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:39,0:39:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:46,0:46:93:0,93,1395 0/0:30,0:30:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:36,0:36:63:0,63,945 0/0:31,0:31:72:0,72,1080 +20 10626775 . G A 113.72 PASS NEGATIVE_TRAIN_SITE;HWP=1.0;AC=2;culprit=QD;MQ0=0;ReadPosRankSum=-0.106;AN=200;InbreedingCoeff=-0.0359;AF=0.006897;GQ_STDDEV=21.65;FS=8.773;DP=17329;GQ_MEAN=34.61;VQSLOD=-1.496;ClippingRankSum=0.495;BaseQRankSum=-1.768;MLEAF=0.004598;MLEAC=8;MQ=60.0;QD=0.36;MQRankSum=-0.158;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:19,0:19:42:0,42,630 0/0:25,0:25:63:0,63,945 0/0:23,0:23:36:0,36,540 0/0:23,0:23:60:0,60,900 0/0:32,0:32:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:20,0:20:36:0,36,540 0/0:25,0:25:60:0,60,900 0/0:30,0:30:51:0,51,1125 0/0:16,0:16:39:0,39,585 0/0:19,0:19:36:0,36,540 0/0:18,0:18:30:0,30,450 0/0:28,0:28:60:0,60,900 0/0:25,0:25:57:0,57,855 0/0:17,0:17:39:0,39,585 0/0:12,0:12:27:0,27,405 0/0:8,0:8:24:0,24,300 0/0:16,0:16:36:0,36,540 0/0:16,0:16:22:0,22,598 0/0:20,0:20:42:0,42,630 0/0:11,0:11:24:0,24,360 0/0:19,0:19:48:0,48,720 0/0:17,0:17:33:0,33,495 0/0:15,0:15:21:0,21,315 0/0:16,0:16:21:0,21,315 0/0:20,0:20:23:0,23,521 0/0:25,0:25:0:0,0,468 0/0:23,0:23:27:0,27,644 0/0:19,0:19:47:0,47,720 0/0:36,0:36:81:0,81,1215 0/0:24,0:24:60:0,60,900 0/0:14,0:14:33:0,33,495 0/0:26,0:26:0:0,0,549 0/0:26,0:26:10:0,10,783 0/0:29,0:29:41:0,41,675 0/0:8,0:8:15:0,15,225 0/0:14,0:14:33:0,33,495 0/0:28,0:28:63:0,63,945 0/0:17,0:17:25:0,25,450 0/0:19,0:19:31:0,31,465 0/0:15,0:15:19:0,19,352 0/0:24,0:24:21:0,21,534 0/0:17,0:17:18:0,18,419 0/0:28,0:28:15:0,15,656 0/0:25,5:30:1:0,1,725 0/0:25,0:25:0:0,0,488 0/0:24,0:24:48:0,48,720 0/1:21,4:25:28:28,0,486 0/0:34,0:34:39:0,39,969 0/0:28,0:28:51:0,51,765 0/1:17,4:21:48:48,0,513 0/0:19,0:19:0:0,0,398 0/0:13,0:13:0:0,0,228 0/0:15,0:15:13:0,13,400 0/0:30,0:30:69:0,69,1035 0/0:13,0:13:0:0,0,339 0/0:27,0:27:49:0,49,765 0/0:27,0:27:7:0,7,592 0/0:16,0:16:0:0,0,328 0/0:42,0:42:75:0,75,1125 0/0:21,0:21:36:0,36,540 0/0:23,0:23:5:0,5,617 0/0:19,0:19:9:0,9,519 0/0:32,0:32:12:0,12,726 0/0:20,0:20:45:0,45,675 0/0:15,0:15:36:0,36,540 0/0:11,0:11:0:0,0,148 0/0:5,0:5:12:0,12,180 0/0:35,0:35:63:0,63,945 0/0:10,0:10:0:0,0,273 0/0:26,0:26:49:0,49,717 0/0:17,0:17:8:0,8,448 0/0:27,0:27:59:0,59,760 0/0:17,0:17:21:0,21,540 0/0:10,0:10:8:0,8,225 0/0:8,0:8:18:0,18,270 0/0:10,0:10:0:0,0,245 0/0:10,0:10:0:0,0,186 0/0:11,0:11:21:0,21,315 0/0:16,0:16:12:0,12,397 0/0:9,0:9:15:0,15,219 0/0:9,0:9:12:0,12,201 0/0:10,0:10:21:0,21,315 0/0:17,0:17:27:0,27,405 0/0:15,0:15:0:0,0,347 0/0:24,0:24:54:0,54,690 0/0:10,0:10:21:0,21,315 0/0:20,0:20:48:0,48,720 0/0:13,0:13:18:0,18,270 0/0:45,0:45:0:0,0,950 0/0:13,0:13:20:0,20,315 0/0:15,0:15:24:0,24,360 0/0:20,0:20:11:0,11,515 0/0:11,0:11:14:0,14,275 0/0:27,0:27:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:13,0:13:0:0,0,218 0/0:15,0:15:33:0,33,495 0/0:7,0:7:8:0,8,178 0/0:9,0:9:12:0,12,180 +20 10627772 rs35357944 C T 3667.33 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.127;AN=200;InbreedingCoeff=-0.0035;AF=0.003448;GQ_STDDEV=50.91;FS=1.906;DP=29810;GQ_MEAN=78.53;POSITIVE_TRAIN_SITE;VQSLOD=3.79;ClippingRankSum=0.109;BaseQRankSum=-3.543;MLEAF=0.003448;MLEAC=6;MQ=60.0;QD=12.18;DB;MQRankSum=-0.298;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:66:0,66,990 0/0:27,0:27:60:0,60,900 0/0:37,0:37:81:0,81,1215 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:31,0:31:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:36,0:36:81:0,81,1215 0/0:36,0:36:81:0,81,1215 0/0:30,0:30:78:0,78,1170 0/0:27,0:27:69:0,69,1035 0/0:32,0:32:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:15,0:15:36:0,36,540 0/0:27,0:27:66:0,66,990 0/0:24,0:24:63:0,63,945 0/0:76,0:76:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:45,0:45:93:0,93,1395 0/0:30,0:30:73:0,73,1189 0/0:48,0:48:99:0,117,1755 0/0:38,0:38:69:0,69,1035 0/0:39,0:39:78:0,78,1170 0/0:44,0:44:99:0,102,1530 0/0:45,0:45:99:0,111,1665 0/0:54,0:54:99:0,114,1710 0/0:29,0:29:63:0,63,945 0/0:41,0:41:90:0,90,1350 0/0:25,0:25:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:41,0:41:99:0,102,1530 0/0:29,0:29:60:0,60,900 0/0:16,0:16:39:0,39,585 0/0:26,0:26:66:0,66,990 0/0:33,0:33:78:0,78,1170 0/0:36,0:36:90:0,90,1350 0/0:50,0:50:99:0,99,1485 0/0:50,0:50:99:0,99,1485 0/0:35,0:35:84:0,84,1260 0/1:26,15:41:99:421,0,976 0/0:32,0:32:78:0,78,1170 0/0:40,0:40:96:0,96,1440 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:29,0:29:65:0,65,1071 0/0:36,0:36:78:0,78,1170 0/0:31,0:31:78:0,78,1170 0/0:48,0:48:99:0,102,1530 0/0:39,0:39:93:0,93,1395 0/0:45,0:45:99:0,100,1645 0/0:26,0:26:63:0,63,945 0/0:32,0:32:75:0,75,1125 0/0:30,0:30:63:0,63,945 0/0:48,0:48:99:0,116,1800 0/0:31,0:31:63:0,63,945 0/0:41,0:41:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:13,0:13:30:0,30,450 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:37,0:37:78:0,78,1170 0/0:30,0:30:66:0,66,990 0/0:44,0:44:96:0,96,1440 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:35,0:35:63:0,63,945 0/0:32,0:32:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:16,0:16:30:0,30,450 0/1:13,8:21:99:217,0,391 0/0:32,0:32:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:36,0:36:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:66:0,66,990 0/0:29,0:29:66:0,66,990 0/0:24,0:24:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:23,0:23:60:0,60,830 0/0:29,0:29:63:0,63,945 0/0:15,0:15:30:0,30,450 0/0:29,0:29:66:0,66,990 +20 10632861 rs45575136 G A 41175.00 PASS HWP=0.3944;AC=8;culprit=FS;MQ0=0;ReadPosRankSum=0.126;AN=200;InbreedingCoeff=0.0443;AF=0.031;GQ_STDDEV=162.42;FS=0.0;DP=25783;GQ_MEAN=101.12;POSITIVE_TRAIN_SITE;VQSLOD=6.23;ClippingRankSum=0.119;BaseQRankSum=-2.621;MLEAF=0.031;MLEAC=54;MQ=59.76;QD=14.53;DB;MQRankSum=0.17;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:25,0:25:63:0,63,945 0/0:34,0:34:67:0,67,1287 0/0:32,0:32:75:0,75,1125 0/1:21,22:43:99:648,0,659 0/0:24,0:24:60:0,60,900 0/0:39,0:39:78:0,78,1395 0/0:35,0:35:63:0,63,1218 0/0:24,0:24:63:0,63,945 0/0:39,0:39:75:0,75,1346 0/1:22,22:44:99:648,0,685 0/0:25,0:25:63:0,63,945 0/0:27,0:27:63:0,63,945 0/1:40,24:64:99:730,0,1275 0/0:23,0:23:63:0,63,945 0/0:30,0:30:69:0,69,1097 0/1:23,23:46:99:649,0,660 0/0:29,0:29:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:32,0:32:81:0,81,1215 0/0:21,0:21:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:62:0,62,945 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:41,0:41:99:0,102,1341 0/1:62,30:92:99:812,0,2220 0/0:42,0:42:99:0,99,1444 0/0:27,0:27:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:45,0:45:99:0,111,1665 0/0:25,0:25:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:32,0:32:72:0,72,1112 0/0:23,0:23:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:40,0:40:93:0,93,1514 0/0:25,0:25:66:0,66,825 0/1:40,29:69:99:810,0,1222 0/0:27,0:27:66:0,66,927 0/0:37,0:37:77:0,77,1260 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:31,0:31:63:0,63,945 0/0:28,0:28:60:0,60,900 0/1:20,18:38:99:499,0,523 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1026 0/0:38,0:38:90:0,90,1229 0/0:29,0:29:61:0,61,999 0/0:28,0:28:75:0,75,1125 0/0:36,0:36:87:0,87,1305 0/0:32,0:32:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/1:17,26:43:99:767,0,495 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:38,0:38:93:0,93,1395 0/0:29,0:29:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:35,0:35:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:38,0:38:80:0,80,1260 0/0:30,0:30:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:28,0:28:61:0,61,990 0/0:25,0:25:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:33,0:33:78:0,78,1170 0/0:25,0:25:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:17,0:17:39:0,39,585 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:29,0:29:60:0,60,900 +20 10632876 rs139574260 A G 1885.70 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.359;AN=200;InbreedingCoeff=-0.0019;AF=0.001724;GQ_STDDEV=35.13;FS=0.0;DP=23432;GQ_MEAN=65.2;POSITIVE_TRAIN_SITE;VQSLOD=4.57;ClippingRankSum=-0.5;BaseQRankSum=3.91;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=16.12;DB;MQRankSum=-0.956;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:25,0:25:63:0,63,945 0/0:34,0:34:67:0,67,1287 0/0:32,0:32:75:0,75,1125 0/0:27,0:27:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:39,0:39:78:0,78,1395 0/0:35,0:35:63:0,63,1218 0/0:24,0:24:63:0,63,945 0/0:39,0:39:75:0,75,1346 0/0:26,0:26:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:30,0:30:69:0,69,1097 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:32,0:32:81:0,81,1215 0/0:21,0:21:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:62:0,62,945 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:41,0:41:99:0,102,1341 0/0:28,0:28:63:0,63,990 0/0:42,0:42:99:0,99,1444 0/0:27,0:27:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:45,0:45:99:0,111,1665 0/0:25,0:25:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:32,0:32:72:0,72,1112 0/0:23,0:23:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:40,0:40:93:0,93,1514 0/0:25,0:25:66:0,66,825 0/0:35,0:35:81:0,81,1298 0/0:27,0:27:66:0,66,927 0/0:37,0:37:77:0,77,1260 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:31,0:31:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:28,0:28:62:0,62,945 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1026 0/0:38,0:38:90:0,90,1229 0/0:29,0:29:61:0,61,999 0/0:28,0:28:75:0,75,1125 0/0:36,0:36:87:0,87,1305 0/0:32,0:32:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:38,0:38:93:0,93,1395 0/0:7,0:7:21:0,21,201 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:35,0:35:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/1:16,17:33:99:580,0,462 0/0:9,0:9:24:0,24,328 0/0:12,0:12:27:0,27,405 0/0:28,0:28:66:0,66,990 0/0:28,0:28:61:0,61,990 0/0:25,0:25:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:33,0:33:78:0,78,1170 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:22,0:22:54:0,54,810 0/0:21,0:21:60:0,60,900 0/0:29,0:29:60:0,60,900 +20 10633237 rs1131695 G A 528941.00 PASS HWP=0.6641;AC=92;culprit=FS;MQ0=0;ReadPosRankSum=0.295;AN=200;InbreedingCoeff=0.015;AF=0.428;GQ_STDDEV=332.95;FS=0.525;DP=37317;GQ_MEAN=332.84;POSITIVE_TRAIN_SITE;VQSLOD=4.43;ClippingRankSum=-0.151;BaseQRankSum=-0.597;MLEAF=0.429;MLEAC=746;MQ=59.54;QD=18.92;DB;MQRankSum=0.032;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,34:34:99:1220,102,0 0/1:32,25:57:99:720,0,845 0/1:14,20:34:99:624,0,364 0/1:23,25:48:99:665,0,617 1/1:1,46:47:99:1576,105,0 1/1:0,50:50:99:1796,150,0 1/1:0,36:36:99:1289,108,0 0/1:26,28:54:99:755,0,814 0/1:29,26:55:99:838,0,906 0/1:14,30:44:99:937,0,349 1/1:0,45:45:99:1578,135,0 1/1:1,26:27:41:820,41,0 0/0:27,0:27:62:0,62,945 0/0:38,0:38:40:0,40,1165 0/0:23,0:23:60:0,60,900 0/0:25,0:25:57:0,57,855 0/1:19,14:33:99:397,0,513 0/0:23,0:23:63:0,63,945 0/1:15,20:35:99:618,0,419 1/1:0,41:41:99:1399,123,0 0/0:27,0:27:61:0,61,945 1/1:0,25:25:75:887,75,0 0/0:29,0:29:63:0,63,945 0/1:49,51:100:99:1536,0,1387 0/0:44,0:44:99:0,120,1800 0/0:29,0:29:66:0,66,1001 0/1:13,17:30:99:526,0,326 0/0:29,0:29:60:0,60,900 0/0:29,0:29:81:0,81,1215 0/1:23,29:52:99:832,0,713 0/1:29,19:48:99:513,0,810 1/1:0,43:43:99:1369,129,0 1/1:0,82:82:99:2859,247,0 0/1:43,51:94:99:1488,0,1300 1/1:0,84:84:99:3053,253,0 0/1:8,23:31:99:622,0,181 0/0:21,0:21:60:0,60,900 0/1:19,14:33:99:409,0,579 1/1:0,45:45:99:1583,135,0 0/0:41,0:41:99:0,111,1665 0/1:18,15:33:99:462,0,502 1/1:0,51:51:99:1835,153,0 0/0:25,0:25:63:0,63,875 0/0:30,0:30:70:0,70,992 0/1:19,15:34:99:440,0,590 0/1:33,22:55:99:627,0,997 0/0:33,0:33:69:0,69,1035 0/1:25,14:39:99:392,0,750 1/1:0,42:42:99:1481,126,0 0/1:32,31:63:99:945,0,942 0/0:32,0:32:72:0,72,1080 0/1:22,25:47:99:768,0,574 0/0:30,0:30:73:0,73,1052 0/1:16,17:33:99:492,0,514 0/1:23,20:43:99:599,0,732 0/1:14,20:34:99:574,0,370 0/1:24,18:42:99:526,0,717 0/1:30,30:60:99:928,0,864 0/1:22,25:47:99:772,0,592 0/1:29,29:58:99:859,0,898 0/1:17,11:28:99:305,0,496 0/0:28,0:28:63:0,63,945 0/0:52,0:52:99:0,120,1800 1/1:0,44:44:99:1526,132,0 0/0:28,0:28:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:7,0:7:21:0,21,280 0/1:7,14:21:99:388,0,215 0/0:39,0:39:96:0,96,1440 0/1:14,15:29:99:443,0,405 0/1:19,28:47:99:755,0,587 0/1:16,10:26:99:269,0,459 0/1:26,20:46:99:501,0,689 0/1:13,20:33:99:597,0,301 1/1:0,33:33:99:1130,99,0 1/1:0,34:34:99:1140,102,0 1/1:0,38:38:99:1265,114,0 0/1:19,19:38:99:484,0,568 0/1:16,16:32:99:429,0,496 0/1:13,9:22:99:243,0,435 0/1:21,8:29:99:216,0,597 0/1:12,10:22:99:269,0,323 0/1:14,12:26:99:348,0,422 0/0:23,0:23:63:0,63,945 0/1:19,23:42:99:694,0,572 0/0:28,0:28:64:0,64,1035 0/1:25,40:65:99:1078,0,597 0/1:24,27:51:99:713,0,612 1/1:0,35:35:99:1238,105,0 1/1:0,74:74:99:2536,222,0 0/1:36,26:62:99:663,0,1141 0/0:25,0:25:60:0,60,900 1/1:0,21:21:63:719,63,0 0/0:25,0:25:69:0,69,1035 0/0:31,0:31:61:0,61,1080 0/0:24,0:24:60:0,60,900 1/1:0,21:21:63:746,63,0 1/1:0,25:25:75:854,75,0 0/1:11,14:25:99:396,0,309 0/0:32,0:32:69:0,69,1035 +20 10636995 rs34742789 C T 3131.93 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.56;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=38.66;FS=0.0;DP=25940;GQ_MEAN=72.6;POSITIVE_TRAIN_SITE;VQSLOD=5.22;ClippingRankSum=0.012;BaseQRankSum=-2.612;MLEAF=0.002874;MLEAC=5;MQ=60.0;QD=14.11;DB;MQRankSum=-0.008;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:66:0,66,778 0/0:28,0:28:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:26,0:26:67:0,67,1014 0/0:26,0:26:63:0,63,945 0/0:24,0:24:62:0,62,939 0/0:29,0:29:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:40,0:40:99:0,102,1530 0/0:24,0:24:60:0,60,900 0/0:32,0:32:78:0,78,1170 0/0:53,0:53:99:0,120,1800 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:54,0:54:99:0,120,1800 0/0:31,0:31:78:0,78,1170 0/0:30,0:30:60:0,60,900 0/0:58,0:58:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:42,0:42:99:0,105,1575 0/0:28,0:28:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:28,0:28:65:0,65,1035 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:27,0:27:60:0,60,900 0/0:36,0:36:96:0,96,1440 0/0:65,0:65:99:0,120,1800 0/0:44,0:44:96:0,96,1440 0/0:31,0:31:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:18,0:18:54:0,54,676 0/0:26,0:26:69:0,69,1035 0/1:21,22:43:99:613,0,651 0/0:26,0:26:72:0,72,1080 0/0:33,0:33:81:0,81,1260 0/1:13,33:46:99:1043,0,338 0/0:47,0:47:99:0,107,1671 0/0:52,0:52:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:28,0:28:60:0,60,990 0/0:37,0:37:87:0,87,1340 0/0:24,0:24:60:0,60,900 0/0:34,0:34:87:0,87,1276 0/0:28,0:28:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:32,0:32:62:0,62,1159 0/0:28,0:28:69:0,69,1035 0/0:30,0:30:71:0,71,1170 0/0:22,0:22:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:32,0:32:72:0,72,1125 0/0:33,0:33:72:0,72,1080 0/0:24,0:24:63:0,63,945 0/0:29,0:29:78:0,78,1170 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,872 0/0:24,0:24:60:0,60,893 0/0:31,0:31:60:0,60,1059 0/0:20,0:20:60:0,60,723 0/0:27,0:27:69:0,69,1035 0/0:25,0:25:63:0,63,945 0/0:28,0:28:69:0,69,1035 0/0:16,0:16:48:0,48,655 0/0:20,0:20:51:0,51,765 0/0:24,0:24:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:26,0:26:66:0,66,1042 0/0:15,0:15:42:0,42,527 0/0:26,0:26:60:0,60,900 0/0:26,0:26:69:0,69,948 0/0:25,0:25:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:38,0:38:81:0,81,1215 0/0:30,0:30:66:0,66,990 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:22,0:22:66:0,66,821 0/0:25,0:25:66:0,66,877 0/0:30,0:30:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:32,0:32:90:0,90,1350 +20 10637057 rs10485741 T C 84247.00 PASS HWP=0.9223;AC=15;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.478;AN=200;InbreedingCoeff=-0.0175;AF=0.057;GQ_STDDEV=231.82;FS=0.522;DP=28574;GQ_MEAN=142.72;POSITIVE_TRAIN_SITE;VQSLOD=4.99;ClippingRankSum=0.023;BaseQRankSum=-0.383;MLEAF=0.057;MLEAC=99;MQ=59.65;QD=13.26;DB;MQRankSum=0.128;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:28,0:28:72:0,72,1080 0/1:29,37:66:99:1018,0,729 0/0:28,0:28:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:26,0:26:67:0,67,1014 0/0:26,0:26:63:0,63,945 0/1:22,21:43:99:604,0,598 0/0:29,0:29:63:0,63,945 0/0:22,0:22:60:0,60,900 0/1:43,25:68:99:713,0,1237 0/0:24,0:24:60:0,60,900 0/0:32,0:32:78:0,78,1170 0/1:34,39:73:99:1069,0,973 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:29,0:29:60:0,60,900 0/1:47,42:89:99:1111,0,1374 0/0:31,0:31:78:0,78,1170 0/0:30,0:30:60:0,60,900 0/0:58,0:58:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/1:26,19:45:99:471,0,715 0/0:28,0:28:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:28,0:28:65:0,65,1035 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:27,0:27:60:0,60,900 0/0:36,0:36:96:0,96,1440 0/1:58,38:96:99:973,0,1612 0/0:44,0:44:96:0,96,1440 0/0:31,0:31:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/1:25,28:53:99:702,0,649 0/0:33,0:33:81:0,81,1260 0/0:36,0:36:81:0,81,1215 0/1:39,27:66:99:717,0,1244 0/1:36,21:57:99:470,0,999 0/0:33,0:33:75:0,75,1125 0/0:28,0:28:60:0,60,990 0/1:22,21:43:99:500,0,639 0/0:24,0:24:60:0,60,900 0/1:27,15:42:99:351,0,849 0/0:28,0:28:63:0,63,945 0/0:27,0:27:60:0,60,900 0/1:23,24:47:99:556,0,670 0/0:28,0:28:69:0,69,1035 0/0:30,0:30:71:0,71,1170 0/0:22,0:22:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:32,0:32:72:0,72,1125 0/0:33,0:33:72:0,72,1080 0/0:24,0:24:63:0,63,945 0/1:31,20:51:99:546,0,968 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,872 0/0:24,0:24:60:0,60,893 0/0:31,0:31:60:0,60,1059 0/0:20,0:20:60:0,60,723 0/0:27,0:27:69:0,69,1035 0/0:25,0:25:63:0,63,945 0/0:28,0:28:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,764 0/0:24,0:24:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:26,0:26:60:0,60,900 0/1:35,22:57:99:631,0,981 0/0:21,0:21:60:0,60,786 0/0:26,0:26:60:0,60,900 0/0:26,0:26:69:0,69,948 0/0:25,0:25:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:38,0:38:81:0,81,1215 0/0:30,0:30:66:0,66,990 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:22,0:22:66:0,66,821 0/0:25,0:25:66:0,66,877 0/0:30,0:30:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 +20 10639098 rs142038344 GCA G 2280.80 PASS HWP=1.0;AC=3;culprit=QD;MQ0=0;ReadPosRankSum=0.366;AN=200;InbreedingCoeff=-0.032;AF=0.026;GQ_STDDEV=35.84;FS=0.0;DP=69292;GQ_MEAN=92.84;VQSLOD=2.31;ClippingRankSum=-0.347;BaseQRankSum=-0.017;MLEAF=0.022;MLEAC=39;MQ=59.74;QD=0.48;DB;MQRankSum=0.464;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:65,0:65:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:101,11:112:14:0,14,3472 0/0:78,0:78:94:0,94,1800 0/0:72,0:72:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:100,0:100:57:0,57,3103 0/0:60,0:60:89:0,89,1800 0/0:80,0:80:91:0,91,1800 0/0:67,0:67:99:0,120,1800 0/0:37,0:37:99:0,99,1485 0/0:54,0:54:96:0,96,1800 0/0:47,0:47:99:0,102,1728 0/0:65,0:65:99:0,120,1800 0/1:58,6:64:42:42,0,2011 0/0:71,0:71:99:0,120,1800 0/0:114,0:114:14:0,14,3441 0/0:91,0:91:32:0,32,2621 0/0:37,0:37:84:0,84,1260 0/0:116,0:116:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:58,0:58:83:0,83,1800 0/0:72,0:72:99:0,118,1800 0/0:63,0:63:99:0,120,1800 0/0:87,0:87:38:0,38,2590 0/0:80,0:80:67:0,67,1800 0/1:64,6:70:16:16,0,2209 0/0:98,0:98:99:0,120,1800 0/0:167,0:167:0:0,0,5434 0/0:203,0:203:39:0,39,6932 0/0:158,0:158:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:47,0:47:99:0,106,1755 0/0:55,0:55:99:0,117,1755 0/0:59,0:59:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:44,0:44:99:0,99,1485 0/0:75,0:75:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:108,0:108:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:47,0:47:99:0,100,1575 0/0:65,0:65:99:0,108,1800 0/0:88,0:88:99:0,120,1800 0/0:60,0:60:99:0,117,1755 0/0:113,0:113:99:0,120,1800 0/0:119,0:119:99:0,108,1800 0/0:78,0:78:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:103,0:103:56:0,56,3296 0/0:92,0:92:65:0,65,1800 0/0:102,0:102:99:0,120,1800 0/0:64,0:64:96:0,96,1800 0/1:86,10:96:99:102,0,2993 0/0:40,0:40:84:0,84,1260 0/0:48,0:48:69:0,69,1800 0/0:58,0:58:41:0,41,1942 0/0:93,0:93:99:0,119,1800 0/0:38,0:38:93:0,93,1395 0/0:67,0:67:99:0,120,1800 0/0:47,0:47:96:0,96,1575 0/0:81,0:81:95:0,95,1800 0/0:54,0:54:99:0,120,1800 0/0:84,0:84:34:0,34,2756 0/0:35,0:35:69:0,69,1035 0/0:43,0:43:84:0,84,1530 0/0:53,0:53:99:0,120,1800 0/0:48,0:48:99:0,108,1620 0/0:54,0:54:99:0,102,1800 0/0:29,0:29:60:0,60,990 0/0:31,0:31:60:0,60,900 0/0:45,0:45:61:0,61,1800 0/0:61,0:61:90:0,90,1800 0/0:53,0:53:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:111,0:111:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:96,0:96:38:0,38,2920 0/0:115,0:115:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:165,16:181:0:0,0,5692 0/0:61,0:61:99:0,120,1800 0/0:39,0:39:84:0,84,1260 0/0:41,0:41:87:0,87,1305 0/0:109,0:109:99:0,120,1800 0/0:42,0:42:86:0,86,1755 0/0:58,0:58:99:0,120,1800 0/0:39,0:39:68:0,68,1508 0/0:67,0:67:99:0,120,1800 +20 10639222 rs1801138 G A 462133.00 PASS HWP=0.0937;AC=25;culprit=FS;MQ0=0;ReadPosRankSum=0.551;AN=200;InbreedingCoeff=0.0608;AF=0.189;GQ_STDDEV=601.05;FS=0.0;DP=67453;GQ_MEAN=458.2;POSITIVE_TRAIN_SITE;VQSLOD=5.99;ClippingRankSum=-0.116;BaseQRankSum=-3.77;MLEAF=0.189;MLEAC=328;MQ=59.64;QD=14.96;DB;MQRankSum=0.067;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:59,58:117:99:1590,0,1758 0/0:74,0:74:99:0,120,1800 0/1:54,49:103:99:1372,0,1681 0/0:59,0:59:99:0,120,1800 0/1:58,42:100:99:1206,0,1782 0/0:72,0:72:99:0,120,1800 0/1:64,49:113:99:1394,0,2017 0/0:63,0:63:99:0,120,1800 0/1:74,54:128:99:1475,0,2271 0/0:66,0:66:99:0,120,1800 0/1:51,43:94:99:1238,0,1560 0/0:60,0:60:89:0,89,1800 0/0:80,0:80:91:0,91,1800 0/0:67,0:67:99:0,120,1800 0/1:21,37:58:99:1118,0,587 0/0:54,0:54:96:0,96,1800 0/0:47,0:47:99:0,102,1728 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:33,0:33:73:0,73,1213 0/0:37,0:37:84:0,84,1260 0/0:116,0:116:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:58,0:58:83:0,83,1800 0/0:72,0:72:99:0,118,1800 0/0:63,0:63:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:80,0:80:67:0,67,1800 0/1:58,43:101:99:1135,0,1720 0/0:98,0:98:99:0,120,1800 0/0:79,0:79:81:0,81,1800 0/0:109,0:109:99:0,105,1800 0/1:84,75:159:99:2023,0,2595 0/0:87,0:87:99:0,120,1800 0/1:60,55:115:99:1418,0,1904 0/0:47,0:47:99:0,106,1755 0/0:55,0:55:99:0,117,1755 0/0:59,0:59:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:44,0:44:99:0,99,1485 0/0:75,0:75:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/1:77,83:160:99:2328,0,2520 0/0:88,0:88:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/1:55,36:91:99:983,0,1685 0/0:47,0:47:99:0,100,1575 0/0:65,0:65:99:0,108,1800 0/0:88,0:88:99:0,120,1800 0/0:60,0:60:99:0,117,1755 0/1:70,62:132:99:1765,0,2140 0/0:106,0:106:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:50,0:50:98:0,98,1755 0/0:102,0:102:99:0,120,1800 0/0:64,0:64:96:0,96,1800 0/0:78,0:78:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:48,0:48:69:0,69,1800 0/0:33,0:33:74:0,74,1170 0/0:93,0:93:99:0,119,1800 0/0:38,0:38:93:0,93,1395 0/0:67,0:67:99:0,120,1800 0/0:47,0:47:96:0,96,1575 0/0:81,0:81:95:0,95,1800 0/0:54,0:54:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:69:0,69,1035 0/0:43,0:43:84:0,84,1530 0/0:53,0:53:99:0,120,1800 0/0:48,0:48:99:0,108,1620 0/0:54,0:54:99:0,102,1800 0/0:29,0:29:60:0,60,990 0/0:31,0:31:60:0,60,900 0/1:34,29:63:99:715,0,1037 0/0:51,0:51:99:0,112,1800 0/1:42,34:76:99:881,0,1380 0/0:87,0:87:99:0,120,1800 1/1:1,114:115:99:3673,302,0 0/0:73,0:73:99:0,120,1800 1/1:0,88:88:99:3045,265,0 0/0:115,0:115:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/1:47,35:82:99:873,0,1428 0/0:39,0:39:84:0,84,1260 0/0:41,0:41:87:0,87,1305 0/1:56,49:105:99:1339,0,1573 0/1:28,40:68:99:1116,0,902 1/1:0,65:65:99:2155,194,0 0/0:37,0:37:78:0,78,1395 0/1:51,32:83:99:813,0,1720 +20 10639336 . C T 1618.31 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=1.55;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=41.22;FS=6.323;DP=57302;GQ_MEAN=106.91;VQSLOD=1.4;ClippingRankSum=0.928;BaseQRankSum=2.88;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=11.32;MQRankSum=0.966;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:52,0:52:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:60,0:60:89:0,89,1800 0/1:51,31:82:99:908,0,1438 0/0:67,0:67:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/1:34,27:61:99:787,0,922 0/0:47,0:47:99:0,102,1728 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:33,0:33:73:0,73,1213 0/0:37,0:37:84:0,84,1260 0/0:116,0:116:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:58,0:58:83:0,83,1800 0/0:72,0:72:99:0,118,1800 0/0:63,0:63:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:80,0:80:67:0,67,1800 0/0:78,0:78:99:0,120,1800 0/0:98,0:98:99:0,120,1800 0/0:79,0:79:81:0,81,1800 0/0:109,0:109:99:0,105,1800 0/0:99,0:99:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:47,0:47:99:0,106,1755 0/0:55,0:55:99:0,117,1755 0/0:59,0:59:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:44,0:44:99:0,99,1485 0/0:75,0:75:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:44,0:44:99:0,99,1492 0/0:47,0:47:99:0,100,1575 0/0:65,0:65:99:0,108,1800 0/0:88,0:88:99:0,120,1800 0/0:60,0:60:99:0,117,1755 0/0:78,0:78:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:50,0:50:98:0,98,1755 0/0:102,0:102:99:0,120,1800 0/0:64,0:64:96:0,96,1800 0/0:78,0:78:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:48,0:48:69:0,69,1800 0/0:33,0:33:74:0,74,1170 0/0:93,0:93:99:0,119,1800 0/0:38,0:38:93:0,93,1395 0/0:67,0:67:99:0,120,1800 0/0:47,0:47:96:0,96,1575 0/0:81,0:81:95:0,95,1800 0/0:54,0:54:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:69:0,69,1035 0/0:43,0:43:84:0,84,1530 0/0:53,0:53:99:0,120,1800 0/0:48,0:48:99:0,108,1620 0/0:54,0:54:99:0,102,1800 0/0:29,0:29:60:0,60,990 0/0:31,0:31:60:0,60,900 0/0:36,0:36:90:0,90,1350 0/0:51,0:51:99:0,112,1800 0/0:50,0:50:87:0,87,1623 0/0:87,0:87:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/0:39,0:39:84:0,84,1260 0/0:41,0:41:87:0,87,1305 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:64:0,64,1099 0/0:44,0:44:93:0,93,1485 0/0:37,0:37:78:0,78,1395 0/0:71,0:71:99:0,120,1800 +20 10639385 rs2273060 A G 934289.00 PASS HWP=0.2784;AC=100;culprit=QD;MQ0=0;ReadPosRankSum=0.48;AN=200;InbreedingCoeff=0.038;AF=0.463;GQ_STDDEV=520.25;FS=1.346;DP=59523;GQ_MEAN=543.78;POSITIVE_TRAIN_SITE;VQSLOD=4.61;ClippingRankSum=-0.258;BaseQRankSum=2.84;MLEAF=0.463;MLEAC=806;MQ=59.63;QD=20.38;DB;MQRankSum=0.087;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:6,51:57:6:1556,6,0 0/1:36,33:69:99:982,0,1038 0/1:31,32:63:99:936,0,952 1/1:0,60:60:99:2190,180,0 1/1:0,75:75:99:2629,225,0 1/1:1,69:70:99:2468,207,0 1/1:4,60:64:74:2040,74,0 0/1:28,38:66:99:1140,0,779 0/1:40,24:64:99:750,0,1175 1/1:1,65:66:99:2304,192,0 1/1:5,67:72:99:2396,143,0 1/1:2,58:60:99:1937,139,0 0/1:36,25:61:99:757,0,1015 0/1:40,28:68:99:757,0,1146 1/1:0,47:47:99:1683,141,0 0/1:30,30:60:99:840,0,909 0/1:39,27:66:99:797,0,1148 0/1:37,29:66:99:768,0,1069 0/1:38,21:59:99:501,0,1152 0/1:30,39:69:99:1192,0,851 0/1:36,20:56:99:495,0,989 0/0:33,0:33:73:0,73,1213 0/0:37,0:37:84:0,84,1260 0/1:94,72:166:99:2088,0,2700 0/0:80,0:80:99:0,120,1800 0/1:25,32:57:99:916,0,740 0/1:43,35:78:99:1026,0,1308 0/0:63,0:63:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/1:50,47:97:99:1390,0,1371 0/1:34,59:93:99:1918,0,746 0/1:54,38:92:99:1155,0,1507 0/0:79,0:79:81:0,81,1800 1/1:0,121:121:99:4592,363,0 1/1:0,134:134:99:4922,402,0 0/1:41,45:86:99:1336,0,941 1/1:0,76:76:99:2813,228,0 0/0:47,0:47:99:0,106,1755 1/1:0,63:63:99:2309,189,0 0/0:59,0:59:99:0,120,1800 0/1:38,25:63:99:733,0,1139 0/1:35,40:75:99:1281,0,1038 0/0:44,0:44:99:0,99,1485 0/1:37,35:72:99:1113,0,1098 0/1:44,37:81:99:1078,0,1336 0/1:48,55:103:99:1575,0,1345 0/1:28,33:61:99:1108,0,833 1/1:0,75:75:99:2668,225,0 0/1:50,34:84:99:1021,0,1510 0/1:49,39:88:99:1223,0,1457 0/1:37,39:76:99:1152,0,1067 0/1:33,24:57:99:717,0,951 0/1:28,19:47:99:547,0,830 0/1:40,23:63:99:735,0,1161 0/1:41,46:87:99:1522,0,1221 1/1:0,68:68:99:2269,203,0 0/1:41,40:81:99:1186,0,1207 0/1:55,55:110:99:1746,0,1693 0/1:44,57:101:99:1767,0,1306 0/0:56,0:56:99:0,120,1800 0/1:38,36:74:99:1058,0,1150 0/0:50,0:50:98:0,98,1755 0/0:102,0:102:99:0,120,1800 1/1:0,79:79:99:2857,237,0 0/1:46,37:83:99:1113,0,1377 0/0:40,0:40:84:0,84,1260 0/1:24,29:53:99:1004,0,691 0/1:20,23:43:99:669,0,547 0/1:51,40:91:99:1226,0,1573 0/0:38,0:38:93:0,93,1395 0/1:38,27:65:99:832,0,1089 0/0:47,0:47:96:0,96,1575 0/1:53,41:94:99:1247,0,1388 0/1:31,28:59:99:846,0,955 1/1:0,57:57:99:2150,171,0 0/0:35,0:35:69:0,69,1035 0/1:32,15:47:99:472,0,976 0/1:31,24:55:99:745,0,906 0/0:48,0:48:99:0,108,1620 1/1:1,68:69:99:2651,171,0 0/0:29,0:29:60:0,60,990 0/0:31,0:31:60:0,60,900 0/1:23,12:35:99:328,0,693 0/0:51,0:51:99:0,112,1800 0/1:35,25:60:99:872,0,1019 0/1:59,59:118:99:1652,0,1694 1/1:0,90:90:99:3205,270,0 0/1:40,33:73:99:930,0,1090 1/1:0,64:64:99:2092,192,0 0/1:56,61:117:99:2018,0,1564 0/1:51,52:103:99:1470,0,1353 0/0:40,0:40:84:0,84,1260 1/1:1,61:62:99:2380,150,0 0/0:39,0:39:84:0,84,1260 0/0:41,0:41:87:0,87,1305 0/1:53,39:92:99:1024,0,1318 1/1:0,38:38:99:1463,114,0 1/1:0,40:40:99:1521,120,0 0/1:21,31:52:99:1013,0,495 0/1:42,36:78:99:1042,0,1168 +20 10644705 rs17536052 G A 40827.10 PASS HWP=0.4903;AC=11;culprit=MQ;MQ0=0;ReadPosRankSum=0.297;AN=200;InbreedingCoeff=0.0321;AF=0.033;GQ_STDDEV=163.9;FS=0.0;DP=33623;GQ_MEAN=113.77;POSITIVE_TRAIN_SITE;VQSLOD=6.84;ClippingRankSum=0.094;BaseQRankSum=-3.024;MLEAF=0.033;MLEAC=57;MQ=60.0;QD=15.46;DB;MQRankSum=0.218;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:39,0:39:93:0,93,1395 0/0:42,0:42:99:0,99,1485 0/0:33,0:33:66:0,66,990 0/1:22,14:36:99:386,0,710 0/0:35,0:35:78:0,78,1170 0/0:44,0:44:99:0,120,1800 0/0:42,0:42:99:0,105,1575 0/0:34,0:34:72:0,72,1080 0/0:49,0:49:99:0,110,1800 0/1:15,26:41:99:717,0,455 0/0:46,0:46:99:0,117,1755 0/0:40,0:40:81:0,81,1215 0/0:27,0:27:60:0,60,900 0/0:41,0:41:99:0,108,1620 0/0:25,0:25:62:0,62,900 0/0:38,0:38:81:0,81,1215 0/0:32,0:32:68:0,68,1105 0/0:32,0:32:69:0,69,1035 0/0:30,0:30:63:0,63,945 0/0:48,0:48:99:0,120,1800 0/0:32,0:32:84:0,84,1260 0/0:35,0:35:84:0,84,1260 0/0:23,0:23:60:0,60,861 0/0:74,0:74:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:28,0:28:63:0,63,945 0/0:23,0:23:60:0,60,898 0/0:31,0:31:81:0,81,1215 0/0:33,0:33:69:0,69,1035 0/0:84,0:84:99:0,120,1800 0/1:53,52:105:99:1594,0,1809 0/0:84,0:84:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:38,0:38:84:0,84,1260 0/0:54,0:54:99:0,120,1800 0/0:35,0:35:87:0,87,1305 0/0:41,0:41:89:0,89,1507 0/0:50,0:50:99:0,108,1620 0/1:35,22:57:99:682,0,1149 0/0:60,0:60:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/1:16,37:53:99:1196,0,477 0/1:30,30:60:99:936,0,993 0/0:42,0:42:96:0,96,1440 0/0:47,0:47:99:0,102,1530 0/1:25,35:60:99:1110,0,801 0/0:40,0:40:99:0,105,1548 0/1:25,26:51:99:767,0,721 0/0:48,0:48:96:0,96,1440 0/0:62,0:62:99:0,120,1800 0/1:21,19:40:99:559,0,697 0/0:56,0:56:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/0:57,0:57:99:0,120,1800 0/0:42,0:42:99:0,117,1755 0/0:49,0:49:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/0:80,0:80:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/1:20,22:42:99:700,0,659 0/0:33,0:33:75:0,75,1125 0/0:33,0:33:78:0,78,1170 0/0:27,0:27:60:0,60,900 0/0:43,0:43:99:0,99,1485 0/0:36,0:36:72:0,72,1080 0/0:61,0:61:99:0,120,1800 0/0:40,0:40:93:0,93,1395 0/0:70,0:70:99:0,120,1800 0/0:37,0:37:93:0,93,1395 0/0:35,0:35:81:0,81,1215 0/0:29,0:29:69:0,69,1035 0/0:40,0:40:99:0,111,1665 0/0:42,0:42:99:0,105,1575 0/0:38,0:38:78:0,78,1170 0/1:19,27:46:99:854,0,648 0/0:26,0:26:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:47,0:47:99:0,105,1575 0/0:42,0:42:87:0,87,1305 0/0:59,0:59:99:0,120,1800 0/0:25,0:25:72:0,72,1000 0/0:41,0:41:81:0,81,1215 0/0:32,0:32:78:0,78,1170 0/0:73,0:73:99:0,120,1800 0/0:32,0:32:72:0,72,1080 0/0:37,0:37:81:0,81,1215 0/0:36,0:36:84:0,84,1260 0/0:28,0:28:66:0,66,990 0/0:20,0:20:42:0,42,630 0/0:17,0:17:22:0,22,585 0/0:32,0:32:81:0,81,1215 0/0:44,0:44:99:0,99,1485 0/0:35,0:35:99:0,99,1485 0/0:39,0:39:84:0,84,1260 +20 10653404 . G A 1552.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=2.24;AN=200;InbreedingCoeff=-7.0E-4;AF=5.747E-4;GQ_STDDEV=53.19;FS=3.069;DP=21095;GQ_MEAN=62.21;VQSLOD=0.621;ClippingRankSum=-2.526;BaseQRankSum=-2.904;MLEAF=5.747E-4;MLEAC=1;MQ=58.36;QD=11.59;MQRankSum=0.51;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:66:0,66,990 0/0:22,0:22:60:0,60,731 0/0:21,0:21:60:0,60,900 0/0:26,0:26:72:0,72,1080 0/0:22,0:22:66:0,66,754 0/0:33,0:33:84:0,84,1305 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,921 0/0:24,0:24:60:0,60,900 0/0:28,0:28:72:0,72,999 0/0:23,0:23:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:31,0:31:84:0,84,1260 0/0:28,0:28:66:0,66,990 0/0:20,0:20:60:0,60,709 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,738 0/0:28,0:28:66:0,66,990 0/0:22,0:22:63:0,63,908 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,789 0/0:26,0:26:63:0,63,945 0/0:24,0:24:63:0,63,753 0/0:23,0:23:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:23,0:23:60:0,60,879 0/0:23,0:23:63:0,63,849 0/0:24,0:24:60:0,60,827 0/0:23,0:23:66:0,66,707 0/0:26,0:26:60:0,60,850 0/0:22,0:22:60:0,60,861 0/0:28,0:28:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:22,0:22:63:0,63,735 0/0:37,0:37:90:0,90,1350 0/0:23,0:23:63:0,63,945 0/0:32,0:32:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:20,0:20:60:0,60,648 0/0:22,0:22:63:0,63,893 0/0:28,0:28:66:0,66,982 0/0:23,0:23:63:0,63,945 0/0:23,0:23:66:0,66,757 0/0:25,0:25:60:0,60,839 0/0:22,0:22:60:0,60,858 0/0:22,0:22:64:0,64,757 0/0:24,0:24:69:0,69,764 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,723 0/0:24,0:24:62:0,62,945 0/0:33,0:33:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,730 0/0:24,0:24:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:20,0:20:60:0,60,674 0/0:27,0:27:61:0,61,924 0/0:22,0:22:60:0,60,793 0/0:24,0:24:57:0,57,786 0/0:21,0:21:51:0,51,765 0/0:27,0:27:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:21,0:21:63:0,63,777 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,899 0/0:20,0:20:60:0,60,647 0/0:23,0:23:60:0,60,790 0/0:23,0:23:63:0,63,945 0/0:20,0:20:60:0,60,659 0/0:11,0:11:29:0,29,393 0/0:18,0:18:24:0,24,585 0/0:25,0:25:60:0,60,900 0/0:27,0:27:68:0,68,880 0/0:24,0:24:60:0,60,856 0/0:20,0:20:60:0,60,685 0/1:66,68:134:99:1603,0,1772 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,732 0/0:22,0:22:63:0,63,854 0/0:25,0:25:66:0,66,978 0/0:27,0:27:63:0,63,945 0/0:19,0:19:42:0,42,630 0/0:36,0:36:99:0,105,1389 0/0:21,0:21:63:0,63,728 0/0:28,0:28:66:0,66,990 0/0:29,0:29:73:0,73,1104 0/0:23,0:23:60:0,60,845 0/0:24,0:24:69:0,69,780 +20 10653469 rs1051415 C T 73912.80 PASS HWP=0.8462;AC=25;culprit=FS;MQ0=0;ReadPosRankSum=0.497;AN=200;InbreedingCoeff=0.0143;AF=0.052;GQ_STDDEV=241.95;FS=0.0;DP=24585;GQ_MEAN=128.19;POSITIVE_TRAIN_SITE;VQSLOD=5.3;ClippingRankSum=-0.019;BaseQRankSum=-1.707;MLEAF=0.052;MLEAC=91;MQ=59.71;QD=13.9;DB;MQRankSum=0.155;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:66:0,66,990 0/0:22,0:22:60:0,60,731 0/0:21,0:21:60:0,60,900 0/1:54,35:89:99:966,0,1457 0/1:38,41:79:99:1163,0,1112 0/1:27,47:74:99:1402,0,782 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,921 0/0:24,0:24:60:0,60,900 0/1:59,45:104:99:1214,0,1719 0/1:40,30:70:99:872,0,1257 0/1:36,30:66:99:819,0,1028 0/1:53,44:97:99:1205,0,1735 0/0:28,0:28:66:0,66,990 0/0:20,0:20:60:0,60,709 0/1:31,34:65:99:1019,0,935 0/0:24,0:24:60:0,60,738 0/0:28,0:28:66:0,66,990 0/0:22,0:22:63:0,63,908 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,789 0/0:26,0:26:63:0,63,945 0/0:24,0:24:63:0,63,753 0/0:23,0:23:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:23,0:23:60:0,60,879 0/0:20,0:20:22:0,22,652 0/0:24,0:24:60:0,60,827 0/0:23,0:23:66:0,66,707 0/0:26,0:26:60:0,60,850 0/0:22,0:22:60:0,60,861 0/0:28,0:28:60:0,60,900 0/0:29,0:29:60:0,60,900 0/1:39,53:92:99:1498,0,1154 0/1:52,46:98:99:1283,0,1496 0/0:23,0:23:63:0,63,945 0/0:32,0:32:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:24,0:24:61:0,61,945 0/0:20,0:20:60:0,60,648 0/1:16,26:42:99:774,0,428 0/0:27,0:27:66:0,66,874 0/0:23,0:23:63:0,63,945 0/1:13,16:29:99:458,0,403 0/0:25,0:25:60:0,60,839 0/1:24,26:50:99:785,0,722 0/1:15,19:34:99:611,0,467 0/1:20,12:32:99:317,0,529 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:23,19:42:99:481,0,661 0/0:24,0:24:62:0,62,945 0/1:25,24:49:99:695,0,754 0/0:25,0:25:60:0,60,900 0/0:24,0:24:63:0,63,945 0/1:20,19:39:99:470,0,519 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,730 0/0:24,0:24:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:29,0:29:60:0,60,900 0/1:13,15:28:99:411,0,421 0/1:19,11:30:99:271,0,630 0/0:22,0:22:60:0,60,793 0/0:15,0:15:27:0,27,539 0/0:22,0:22:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:21,0:21:63:0,63,777 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,894 0/0:20,0:20:60:0,60,647 0/0:23,0:23:60:0,60,790 0/0:26,0:26:60:0,60,900 0/1:18,14:32:99:402,0,643 0/1:16,16:32:99:385,0,527 0/0:21,0:21:60:0,60,900 0/0:25,0:25:34:0,34,810 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,856 0/1:32,17:49:99:427,0,934 0/0:30,0:30:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,732 0/0:22,0:22:63:0,63,854 0/0:25,0:25:66:0,66,978 0/0:27,0:27:63:0,63,945 0/1:19,9:28:99:240,0,556 0/1:49,33:82:99:915,0,1715 0/0:21,0:21:63:0,63,728 0/0:21,0:21:60:0,60,865 0/0:29,0:29:73:0,73,1104 0/0:27,0:27:60:0,60,945 0/0:24,0:24:69:0,69,780 +20 11898991 . A G 2330.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.206;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=63.69;FS=0.0;DP=38258;GQ_MEAN=87.97;VQSLOD=2.52;ClippingRankSum=-0.284;BaseQRankSum=3.01;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=18.35;MQRankSum=-1.587;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:72:0,72,1080 0/0:31,0:31:75:0,75,1125 0/0:32,0:32:78:0,78,1170 0/0:47,0:47:99:0,114,1710 0/0:39,0:39:93:0,93,1395 0/0:54,0:54:99:0,109,1755 0/0:40,0:40:87:0,87,1305 0/0:40,0:40:84:0,84,1260 0/0:43,0:43:99:0,111,1665 0/0:44,0:44:93:0,93,1395 0/0:38,0:38:84:0,84,1260 0/0:30,0:30:72:0,72,1080 0/0:50,0:50:99:0,114,1710 0/0:41,0:41:84:0,84,1260 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:75:0,75,1125 0/0:26,0:26:66:0,66,990 0/0:37,0:37:84:0,84,1260 0/0:31,0:31:66:0,66,990 0/0:34,0:34:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:42,0:42:75:0,75,1125 0/0:52,0:52:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:45,0:45:96:0,96,1440 0/0:40,0:40:81:0,81,1215 0/0:32,0:32:81:0,81,1215 0/0:74,0:74:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:53,0:53:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:36,0:36:90:0,90,1350 0/0:118,0:118:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:36,0:36:78:0,78,1170 0/0:46,0:46:99:0,117,1755 0/0:56,0:56:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:53,0:53:99:0,111,1665 0/0:33,0:33:75:0,75,1125 0/0:51,0:51:99:0,120,1800 0/0:44,0:44:93:0,93,1395 0/0:74,0:74:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:47,0:47:99:0,117,1755 0/0:51,0:51:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:55,0:55:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:42,0:42:90:0,90,1350 0/0:39,0:39:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:36,0:36:72:0,72,1080 0/0:32,0:32:78:0,78,1170 0/0:31,0:31:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:36,0:36:87:0,87,1305 0/0:50,0:50:99:0,114,1710 0/0:27,0:27:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:35,0:35:72:0,72,1080 0/0:62,0:62:99:0,120,1800 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:66:0,66,990 0/0:42,0:42:87:0,87,1305 0/1:57,70:127:99:2381,0,1821 0/0:35,0:35:63:0,63,945 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:30,0:30:66:0,66,990 0/0:33,0:33:62:0,62,1035 +20 11899261 rs191954510 G A 8132.93 PASS HWP=1.0;AC=1;culprit=ReadPosRankSum;MQ0=0;ReadPosRankSum=0.125;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=112.22;FS=1.129;DP=37192;GQ_MEAN=93.32;POSITIVE_TRAIN_SITE;VQSLOD=4.41;ClippingRankSum=-0.719;BaseQRankSum=-4.362;MLEAF=0.002874;MLEAC=5;MQ=59.67;QD=14.87;DB;MQRankSum=-0.115;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:72:0,72,1080 0/0:31,0:31:75:0,75,1125 0/0:32,0:32:78:0,78,1170 0/0:47,0:47:99:0,114,1710 0/0:39,0:39:93:0,93,1395 0/0:54,0:54:99:0,109,1755 0/0:40,0:40:87:0,87,1305 0/0:40,0:40:84:0,84,1260 0/0:43,0:43:99:0,111,1665 0/0:44,0:44:93:0,93,1395 0/0:38,0:38:84:0,84,1260 0/0:30,0:30:72:0,72,1080 0/0:50,0:50:99:0,114,1710 0/0:41,0:41:84:0,84,1260 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:75:0,75,1125 0/0:26,0:26:66:0,66,990 0/0:37,0:37:84:0,84,1260 0/0:31,0:31:66:0,66,990 0/0:34,0:34:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:42,0:42:75:0,75,1125 0/0:52,0:52:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:45,0:45:96:0,96,1440 0/0:40,0:40:81:0,81,1215 0/0:32,0:32:81:0,81,1215 0/0:74,0:74:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:53,0:53:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:36,0:36:90:0,90,1350 0/1:58,54:112:99:1558,0,1775 0/0:87,0:87:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:36,0:36:78:0,78,1170 0/0:46,0:46:99:0,117,1755 0/0:56,0:56:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:53,0:53:99:0,111,1665 0/0:33,0:33:75:0,75,1125 0/0:51,0:51:99:0,120,1800 0/0:44,0:44:93:0,93,1395 0/0:74,0:74:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:47,0:47:99:0,117,1755 0/0:51,0:51:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:55,0:55:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:42,0:42:90:0,90,1350 0/0:39,0:39:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:36,0:36:72:0,72,1080 0/0:32,0:32:78:0,78,1170 0/0:31,0:31:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:36,0:36:87:0,87,1305 0/0:50,0:50:99:0,114,1710 0/0:27,0:27:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:35,0:35:72:0,72,1080 0/0:62,0:62:99:0,120,1800 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:66:0,66,990 0/0:42,0:42:87:0,87,1305 0/0:32,0:32:63:0,63,945 0/0:35,0:35:63:0,63,945 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:30,0:30:66:0,66,990 0/0:33,0:33:62:0,62,1035 +20 11903654 rs35364034 G A 245282.00 PASS HWP=0.5889;AC=9;culprit=FS;MQ0=0;ReadPosRankSum=0.836;AN=200;InbreedingCoeff=0.0238;AF=0.086;GQ_STDDEV=567.01;FS=0.0;DP=42743;GQ_MEAN=307.01;POSITIVE_TRAIN_SITE;VQSLOD=6.4;ClippingRankSum=-0.371;BaseQRankSum=0.686;MLEAF=0.086;MLEAC=149;MQ=59.68;QD=14.85;DB;MQRankSum=0.363;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:60:0,60,900 0/0:30,0:30:84:0,84,1260 0/0:27,0:27:60:0,60,1094 0/0:39,0:39:95:0,95,1575 0/0:35,0:35:79:0,79,1215 0/0:36,0:36:84:0,84,1260 0/0:36,0:36:90:0,90,1350 0/0:29,0:29:63:0,63,1125 0/0:38,0:38:97:0,97,1492 0/0:28,0:28:63:0,63,945 0/0:31,0:31:78:0,78,1170 0/0:25,0:25:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:37,0:37:64:0,64,1248 0/0:24,0:24:60:0,60,900 0/0:35,0:35:78:0,78,1170 0/0:22,0:22:63:0,63,829 0/0:26,0:26:78:0,78,953 0/0:21,0:21:60:0,60,900 0/0:32,0:32:78:0,78,1272 0/0:25,0:25:60:0,60,900 0/0:30,0:30:84:0,84,1260 0/0:28,0:28:60:0,60,900 0/0:61,0:61:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:44,0:44:99:0,117,1755 0/0:41,0:41:90:0,90,1350 0/0:46,0:46:93:0,93,1395 0/0:30,0:30:69:0,69,1123 0/0:42,0:42:87:0,87,1305 0/0:34,0:34:78:0,78,1170 0/0:34,0:34:93:0,93,1395 0/0:66,0:66:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:30,0:30:63:0,63,1214 0/0:33,0:33:70:0,70,1260 0/0:24,0:24:60:0,60,900 0/0:35,0:35:71:0,71,1211 0/0:58,0:58:99:0,120,1800 0/0:38,0:38:93:0,93,1395 0/0:38,0:38:93:0,93,1312 0/0:34,0:34:84:0,84,1260 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:99:0,111,1665 0/0:70,0:70:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:50,0:50:99:0,114,1710 0/0:58,0:58:99:0,120,1800 0/0:43,0:43:99:0,114,1800 0/0:38,0:38:84:0,84,1260 0/0:35,0:35:82:0,82,1223 0/0:27,0:27:78:0,78,1170 0/0:48,0:48:99:0,108,1800 0/0:36,0:36:93:0,93,1304 0/0:59,0:59:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:37,0:37:87:0,87,1305 0/0:46,0:46:99:0,106,1755 0/1:90,98:188:99:2919,0,2843 0/0:49,0:49:99:0,106,1800 0/0:39,0:39:99:0,99,1611 0/0:34,0:34:90:0,90,1350 0/0:26,0:26:60:0,60,900 0/0:20,0:20:60:0,60,780 0/0:65,0:65:99:0,120,1800 0/1:50,34:84:99:949,0,1475 0/1:74,55:129:99:1632,0,2182 0/0:36,0:36:83:0,83,1219 0/0:57,0:57:99:0,120,1800 0/0:30,0:30:72:0,72,1080 0/0:29,0:29:75:0,75,1125 0/0:28,0:28:62:0,62,945 0/0:29,0:29:63:0,63,945 0/0:35,0:35:78:0,78,1170 0/0:29,0:29:66:0,66,1125 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:33,0:33:81:0,81,1215 0/0:32,0:32:81:0,81,1215 0/0:47,0:47:99:0,105,1575 0/0:22,0:22:63:0,63,838 0/0:23,0:23:66:0,66,990 0/0:25,0:25:72:0,72,1080 1/1:0,168:168:99:5919,505,0 0/1:70,68:138:99:1845,0,1941 0/0:28,0:28:63:0,63,990 0/0:31,0:31:66:0,66,1080 0/0:25,0:25:63:0,63,945 0/0:35,0:35:73:0,73,1395 0/0:27,0:27:60:0,60,900 0/1:43,47:90:99:1345,0,1379 0/0:33,0:33:70:0,70,1125 0/1:23,44:67:99:1306,0,665 0/1:63,54:117:99:1528,0,1811 +20 12989901 rs3761896 T C 642178.00 PASS HWP=2.0E-4;AC=52;culprit=FS;MQ0=0;ReadPosRankSum=0.45;AN=200;InbreedingCoeff=0.135;AF=0.21;GQ_STDDEV=723.54;FS=0.0;DP=67675;GQ_MEAN=537.56;POSITIVE_TRAIN_SITE;VQSLOD=7.05;ClippingRankSum=-0.228;BaseQRankSum=-1.124;MLEAF=0.21;MLEAC=366;MQ=59.59;QD=16.84;DB;MQRankSum=0.281;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:56,56:112:99:1551,0,1553 0/1:50,61:111:99:1652,0,1445 0/0:48,0:48:99:0,111,1665 0/0:63,0:63:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/1:53,68:121:99:1831,0,1493 0/1:62,51:113:99:1346,0,1707 0/0:59,0:59:99:0,120,1800 0/0:36,0:36:87:0,87,1305 0/0:51,0:51:99:0,110,1663 0/0:60,0:60:99:0,120,1800 1/1:0,120:120:99:4072,361,0 1/1:5,104:109:99:3349,247,0 0/0:28,0:28:66:0,66,990 1/1:0,81:81:99:2655,243,0 0/0:38,0:38:87:0,87,1305 1/1:0,103:103:99:3330,309,0 0/0:30,0:30:60:0,60,900 0/0:40,0:40:84:0,84,1260 0/0:35,0:35:76:0,76,1115 0/0:40,0:40:87:0,87,1305 0/1:50,39:89:99:998,0,1507 0/0:80,0:80:99:0,120,1800 0/1:76,76:152:99:2288,0,2213 0/0:76,0:76:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/1:47,62:109:99:1904,0,1385 0/1:91,44:135:99:1049,0,2597 0/1:78,70:148:99:1951,0,2187 0/0:36,0:36:63:0,63,945 0/0:59,0:59:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:33,0:33:81:0,81,1215 0/1:53,66:119:99:1683,0,1462 0/0:57,0:57:99:0,120,1800 0/1:62,46:108:99:1245,0,1963 0/1:57,49:106:99:1359,0,1707 0/1:59,45:104:99:1241,0,1778 1/1:0,107:107:99:3598,321,0 0/1:55,53:108:99:1437,0,1698 0/0:88,0:88:99:0,120,1800 0/1:88,67:155:99:1865,0,2687 0/0:59,0:59:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/1:78,85:163:99:2543,0,2464 0/0:95,0:95:99:0,120,1800 0/1:57,44:101:99:1242,0,1819 0/0:52,0:52:99:0,120,1800 0/1:58,49:107:99:1274,0,1825 0/1:44,48:92:99:1375,0,1322 0/0:58,0:58:99:0,120,1800 0/1:53,49:102:99:1184,0,1575 0/1:78,67:145:99:1865,0,2364 0/0:89,0:89:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/1:43,42:85:99:1162,0,1215 0/0:41,0:41:96:0,96,1575 0/0:76,0:76:99:0,120,1800 0/0:70,0:70:99:0,120,1800 1/1:0,104:104:99:3512,312,0 1/1:0,105:105:99:3526,316,0 0/0:28,0:28:60:0,60,900 0/0:27,0:27:63:0,63,945 0/1:77,78:155:99:2375,0,2418 0/1:36,34:70:99:1049,0,1026 0/1:56,61:117:99:1576,0,1675 0/1:64,53:117:99:1419,0,1893 0/0:57,0:57:99:0,120,1800 0/1:44,33:77:99:864,0,1355 0/0:31,0:31:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:37,0:37:87:0,87,1305 0/0:27,0:27:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:27,0:27:69:0,69,1035 0/0:30,0:30:64:0,64,990 0/0:31,0:31:66:0,66,990 0/1:30,23:53:99:651,0,962 0/0:38,0:38:81:0,81,1215 0/1:47,52:99:99:1466,0,1376 0/0:52,0:52:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/1:40,47:87:99:1368,0,1036 0/1:106,77:183:99:2178,0,3096 0/0:50,0:50:99:0,102,1530 0/0:68,0:68:99:0,120,1800 0/1:35,41:76:99:1137,0,1009 0/0:35,0:35:84:0,84,1260 0/0:52,0:52:99:0,120,1800 0/0:57,0:57:99:0,117,1755 1/1:0,84:84:99:3052,252,0 1/1:1,94:95:99:3187,243,0 0/1:27,31:58:99:975,0,713 0/1:44,46:90:99:1292,0,1310 +20 12990044 rs3761895 T C 840733.00 PASS HWP=0.0;AC=149;culprit=FS;MQ0=0;ReadPosRankSum=0.458;AN=200;InbreedingCoeff=0.2963;AF=0.541;GQ_STDDEV=364.74;FS=0.0;DP=46350;GQ_MEAN=343.83;POSITIVE_TRAIN_SITE;VQSLOD=4.07;ClippingRankSum=-0.082;BaseQRankSum=1.67;MLEAF=0.541;MLEAC=942;MQ=59.59;QD=23.87;DB;MQRankSum=0.313;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,52:52:99:1782,156,0 1/1:0,37:37:99:1319,111,0 1/1:0,48:48:99:1648,144,0 1/1:0,62:62:99:2131,186,0 0/1:34,32:66:99:856,0,856 0/1:25,31:56:99:864,0,677 1/1:1,52:53:99:1756,156,0 1/1:1,31:32:59:1119,59,0 1/1:0,59:59:99:2184,177,0 1/1:0,37:37:99:1285,111,0 0/1:18,30:48:99:902,0,496 0/1:30,29:59:99:809,0,766 1/1:0,44:44:99:1653,132,0 1/1:0,50:50:99:1790,150,0 0/0:28,0:28:66:0,66,990 1/1:0,49:49:99:1742,147,0 0/1:17,23:40:99:624,0,511 1/1:0,59:59:99:2006,177,0 1/1:0,32:32:96:1069,96,0 0/0:40,0:40:84:0,84,1260 0/0:35,0:35:76:0,76,1115 1/1:0,42:42:99:1463,126,0 1/1:0,48:48:99:1639,144,0 1/1:0,80:80:99:2725,239,0 1/1:0,71:71:99:2509,212,0 0/0:76,0:76:99:0,120,1800 1/1:0,82:82:99:2878,245,0 1/1:0,67:67:99:2293,200,0 1/1:0,55:55:99:1987,164,0 1/1:0,52:52:99:1882,156,0 1/1:0,34:34:99:1266,102,0 0/0:59,0:59:99:0,120,1800 1/1:0,80:80:99:2778,240,0 1/1:0,55:55:99:1961,164,0 0/1:70,53:123:99:1390,0,1960 0/1:40,22:62:99:483,0,975 0/0:33,0:33:81:0,81,1215 1/1:0,28:28:84:1022,84,0 1/1:0,58:58:99:1928,172,0 0/1:47,36:83:99:899,0,1328 1/1:0,50:50:99:1768,150,0 1/1:0,67:67:99:2409,201,0 1/1:0,56:56:99:1954,167,0 0/1:34,29:63:99:935,0,975 1/1:0,87:87:99:3017,258,0 1/1:0,73:73:99:2665,219,0 1/1:0,57:57:99:2079,171,0 0/1:42,51:93:99:1508,0,1178 1/1:0,85:85:99:3216,254,0 1/1:2,91:93:99:3435,202,0 1/1:0,58:58:99:1955,172,0 0/0:52,0:52:99:0,120,1800 1/1:0,53:53:99:1770,159,0 1/1:0,30:30:88:1059,88,0 0/1:30,28:58:99:749,0,805 0/1:37,32:69:99:991,0,1003 1/1:0,96:96:99:3256,285,0 0/1:44,49:93:99:1475,0,1195 1/1:0,83:83:99:2763,247,0 1/1:1,68:69:99:2564,169,0 1/1:0,60:60:99:2038,179,0 0/0:41,0:41:96:0,96,1575 1/1:0,78:78:99:2931,234,0 0/1:39,31:70:99:977,0,1205 1/1:0,55:55:99:1911,163,0 1/1:0,42:42:99:1451,126,0 1/1:0,26:26:77:896,77,0 0/0:13,0:13:27:0,27,405 1/1:1,78:79:99:2965,234,0 1/1:0,19:19:56:646,56,0 1/1:0,51:51:99:1977,153,0 0/1:23,18:41:99:538,0,688 1/1:0,60:60:99:2194,179,0 1/1:0,32:32:96:1244,96,0 0/0:31,0:31:69:0,69,1035 0/1:9,6:15:99:128,0,277 1/1:0,39:39:99:1398,116,0 1/1:0,26:26:78:944,78,0 1/1:0,26:26:78:902,78,0 1/1:0,29:29:86:1051,86,0 0/1:14,18:32:99:560,0,393 1/1:0,29:29:86:930,86,0 1/1:0,30:30:89:940,89,0 1/1:0,38:38:99:1406,114,0 0/1:22,18:40:99:561,0,644 0/1:26,24:50:99:774,0,702 0/1:47,35:82:99:989,0,1245 1/1:0,54:54:99:1897,162,0 0/1:17,21:38:99:609,0,443 0/1:50,36:86:99:1113,0,1494 0/0:50,0:50:99:0,102,1530 0/1:42,27:69:99:698,0,1217 0/1:20,20:40:99:521,0,472 0/1:16,19:35:99:529,0,488 0/0:52,0:52:99:0,120,1800 0/1:32,24:56:99:721,0,768 1/1:0,40:40:99:1429,120,0 1/1:1,37:38:72:1294,72,0 1/1:0,10:10:30:409,30,0 0/1:15,19:34:99:545,0,401 +20 12990057 rs3761894 T A 244627.00 PASS HWP=0.0015;AC=52;culprit=FS;MQ0=0;ReadPosRankSum=0.366;AN=200;InbreedingCoeff=0.1128;AF=0.218;GQ_STDDEV=266.97;FS=0.0;DP=38351;GQ_MEAN=237.26;POSITIVE_TRAIN_SITE;VQSLOD=6.67;ClippingRankSum=0.053;BaseQRankSum=-1.833;MLEAF=0.218;MLEAC=379;MQ=59.6;QD=15.67;DB;MQRankSum=0.07;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:24,24:48:99:671,0,606 0/1:17,16:33:99:434,0,504 0/0:30,0:30:72:0,72,1080 0/0:38,0:38:81:0,81,1215 0/0:37,0:37:90:0,90,1350 0/0:39,0:39:90:0,90,1350 0/1:27,23:50:99:554,0,696 0/1:20,14:34:99:385,0,552 0/0:39,0:39:93:0,93,1395 0/0:24,0:24:63:0,63,945 0/0:47,0:47:85:0,85,1566 0/0:30,0:30:63:0,63,945 1/1:0,36:36:99:1281,108,0 1/1:1,45:46:99:1568,135,0 0/0:28,0:28:66:0,66,990 1/1:0,41:41:99:1371,123,0 0/0:27,0:27:60:0,60,900 1/1:0,48:48:99:1647,144,0 0/0:11,0:11:27:0,27,405 0/0:40,0:40:84:0,84,1260 0/0:35,0:35:76:0,76,1115 0/0:33,0:33:81:0,81,1215 0/1:25,22:47:99:561,0,740 0/0:43,0:43:90:0,90,1350 0/1:42,20:62:99:493,0,1166 0/0:76,0:76:99:0,120,1800 0/0:48,0:48:96:0,96,1440 0/1:32,19:51:99:513,0,852 0/1:27,24:51:99:542,0,769 0/1:21,28:49:99:701,0,603 0/0:25,0:25:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:33,0:33:81:0,81,1215 0/1:14,11:25:99:315,0,389 0/0:34,0:34:69:0,69,1035 0/1:39,27:66:99:641,0,1221 0/1:16,26:42:99:793,0,430 0/1:32,32:64:99:896,0,915 1/1:0,52:52:99:1792,156,0 0/1:33,25:58:99:711,0,1000 0/0:58,0:58:99:0,120,1800 0/1:40,28:68:99:743,0,1173 0/0:42,0:42:98:0,98,1485 0/0:73,0:73:99:0,120,1800 0/1:38,39:77:99:1112,0,1058 0/0:55,0:55:99:0,120,1800 0/1:34,27:61:99:768,0,1013 0/0:52,0:52:99:0,120,1800 0/1:34,20:54:99:514,0,1020 0/1:12,15:27:99:410,0,308 0/0:33,0:33:78:0,78,1170 0/1:30,32:62:99:800,0,810 0/1:39,48:87:99:1371,0,1128 0/0:51,0:51:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:46,0:46:99:0,105,1575 0/1:25,27:52:99:713,0,707 0/0:41,0:41:96:0,96,1575 0/0:48,0:48:99:0,105,1575 0/0:48,0:48:99:0,114,1710 1/1:0,53:53:99:1791,159,0 1/1:0,42:42:99:1412,126,0 0/0:25,0:25:60:0,60,900 0/0:13,0:13:27:0,27,405 0/1:40,39:79:99:1055,0,1122 0/1:7,9:16:99:227,0,213 0/1:30,15:45:99:334,0,898 0/1:16,13:29:99:339,0,440 0/0:40,0:40:93:0,93,1395 0/1:12,10:22:99:236,0,365 0/0:31,0:31:69:0,69,1035 0/0:11,0:11:21:0,21,315 0/0:27,0:27:69:0,69,1035 0/0:20,0:20:60:0,60,762 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:11,0:11:21:0,21,315 0/1:18,12:30:99:260,0,518 0/0:22,0:22:60:0,60,900 0/1:18,17:35:99:449,0,508 0/0:32,0:32:63:0,63,945 0/0:46,0:46:93:0,93,1395 0/0:31,0:31:66:0,66,990 0/1:13,19:32:99:539,0,381 0/1:40,27:67:99:730,0,1199 0/0:50,0:50:99:0,102,1530 0/0:34,0:34:96:0,96,1440 0/1:21,18:39:99:485,0,577 0/0:27,0:27:63:0,63,945 0/0:52,0:52:99:0,120,1800 0/0:30,0:30:63:0,63,945 1/1:0,35:35:99:1146,105,0 1/1:1,32:33:61:1101,61,0 0/1:2,6:8:51:191,0,51 0/1:16,17:33:99:467,0,509 +20 12990059 rs75655091 T G 60468.40 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.45;AN=200;InbreedingCoeff=0.0066;AF=0.045;GQ_STDDEV=202.65;FS=0.0;DP=33834;GQ_MEAN=132.43;POSITIVE_TRAIN_SITE;VQSLOD=5.91;ClippingRankSum=0.041;BaseQRankSum=1.71;MLEAF=0.045;MLEAC=78;MQ=59.62;QD=14.85;DB;MQRankSum=0.342;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:75:0,75,1125 0/0:27,0:27:63:0,63,945 0/0:30,0:30:72:0,72,1080 0/0:38,0:38:81:0,81,1215 0/0:37,0:37:90:0,90,1350 0/0:39,0:39:90:0,90,1350 0/0:31,0:31:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:39,0:39:93:0,93,1395 0/0:24,0:24:63:0,63,945 0/0:47,0:47:85:0,85,1566 0/0:30,0:30:63:0,63,945 0/0:31,0:31:75:0,75,1125 0/0:37,0:37:93:0,93,1395 0/0:28,0:28:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:11,0:11:27:0,27,405 0/0:40,0:40:84:0,84,1260 0/1:18,17:35:99:470,0,476 0/0:33,0:33:81:0,81,1215 0/0:34,0:34:93:0,93,1395 0/0:43,0:43:90:0,90,1350 0/0:40,0:40:90:0,90,1350 0/1:32,43:75:99:1332,0,903 0/0:48,0:48:96:0,96,1440 0/0:32,0:32:78:0,78,1170 0/0:32,0:32:87:0,87,1305 0/0:35,0:35:61:0,61,1145 0/0:25,0:25:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:33,0:33:81:0,81,1215 0/0:24,0:24:63:0,63,945 0/0:34,0:34:69:0,69,1035 0/0:46,0:46:99:0,105,1575 0/0:30,0:30:72:0,72,1080 0/0:55,0:55:99:0,120,1800 0/0:34,0:34:78:0,78,1170 0/0:40,0:40:96:0,96,1440 0/0:58,0:58:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:42,0:42:98:0,98,1485 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,111,1665 0/0:55,0:55:99:0,120,1800 0/0:44,0:44:99:0,114,1710 0/0:52,0:52:99:0,120,1800 0/0:38,0:38:90:0,90,1350 0/0:21,0:21:22:0,22,638 0/0:33,0:33:78:0,78,1170 0/0:43,0:43:99:0,105,1575 0/0:65,0:65:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:46,0:46:99:0,105,1575 0/0:29,0:29:66:0,66,990 0/0:41,0:41:96:0,96,1575 0/0:48,0:48:99:0,105,1575 0/0:48,0:48:99:0,114,1710 0/0:37,0:37:90:0,90,1350 0/0:31,0:31:64:0,64,1035 0/0:25,0:25:60:0,60,900 0/0:13,0:13:27:0,27,405 0/0:66,0:66:99:0,120,1800 0/0:13,0:13:30:0,30,450 0/0:33,0:33:78:0,78,1170 0/0:25,0:25:63:0,63,945 0/0:40,0:40:93:0,93,1395 0/0:12,0:12:27:0,27,405 0/0:31,0:31:69:0,69,1035 0/0:11,0:11:21:0,21,315 0/0:27,0:27:69:0,69,1035 0/0:16,0:16:42:0,42,630 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:46,0:46:93:0,93,1395 0/0:31,0:31:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:47,0:47:99:0,117,1755 0/0:50,0:50:99:0,102,1530 0/0:34,0:34:96:0,96,1440 0/0:26,0:26:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:52,0:52:99:0,120,1800 0/0:30,0:30:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:7,0:7:12:0,12,180 0/0:26,0:26:69:0,69,1035 +20 13029764 rs1431433 A C 2390780.00 PASS HWP=1.0;AC=200;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.447;AN=200;InbreedingCoeff=-0.0075;AF=0.993;GQ_STDDEV=166.66;FS=4.821;DP=72082;GQ_MEAN=260.05;POSITIVE_TRAIN_SITE;VQSLOD=3.38;ClippingRankSum=0.487;BaseQRankSum=-1.559;MLEAF=0.993;MLEAC=1727;MQ=59.64;QD=33.25;DB;MQRankSum=0.385;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,80:80:99:2776,240,0 1/1:0,68:68:99:2275,204,0 1/1:0,73:73:99:2469,219,0 1/1:0,71:71:99:2426,212,0 1/1:0,95:95:99:3183,286,0 1/1:0,71:71:99:2377,213,0 1/1:0,89:89:99:2974,268,0 1/1:0,65:65:99:2249,195,0 1/1:0,106:106:99:3661,319,0 1/1:0,75:75:99:2518,225,0 1/1:0,86:86:99:2996,259,0 1/1:0,72:72:99:2405,216,0 1/1:0,84:84:99:2843,252,0 1/1:0,68:68:99:2280,204,0 1/1:0,74:74:99:2343,222,0 1/1:0,86:86:99:2897,258,0 1/1:0,76:76:99:2549,228,0 1/1:0,107:107:99:3559,322,0 1/1:0,88:88:99:2960,265,0 1/1:0,114:114:99:3826,343,0 1/1:0,95:95:99:3197,286,0 1/1:0,81:81:99:2664,243,0 1/1:0,102:102:99:3350,307,0 1/1:0,146:146:99:4891,438,0 1/1:0,121:121:99:4159,364,0 1/1:0,106:106:99:3438,319,0 1/1:0,111:111:99:3659,333,0 1/1:0,99:99:99:3185,296,0 1/1:0,68:68:99:2348,204,0 1/1:0,68:68:99:2296,204,0 1/1:0,54:54:99:1743,162,0 1/1:0,69:69:99:2289,207,0 1/1:0,180:180:99:6423,541,0 1/1:0,180:180:99:6224,540,0 1/1:0,170:170:99:5923,511,0 1/1:0,56:56:99:1815,168,0 1/1:0,53:53:99:1815,159,0 1/1:0,110:110:99:3673,331,0 1/1:0,88:88:99:2954,265,0 1/1:0,153:153:99:4837,459,0 1/1:0,73:73:99:2425,219,0 1/1:0,92:92:99:3028,276,0 1/1:0,97:97:99:3188,292,0 1/1:0,95:95:99:3198,286,0 1/1:0,101:101:99:3394,303,0 1/1:0,135:135:99:4474,405,0 1/1:0,118:118:99:3908,355,0 1/1:0,145:145:99:4816,435,0 1/1:0,96:96:99:3406,288,0 1/1:0,141:141:99:4773,423,0 1/1:0,95:95:99:3276,286,0 1/1:0,93:93:99:2993,279,0 1/1:0,116:116:99:3732,348,0 1/1:0,100:100:99:3440,301,0 1/1:0,144:144:99:5034,433,0 1/1:0,106:106:99:3361,318,0 1/1:0,126:126:99:4244,379,0 1/1:0,138:138:99:4602,414,0 1/1:0,139:139:99:4605,418,0 1/1:0,113:113:99:4100,340,0 1/1:0,94:94:99:3047,282,0 1/1:0,95:95:99:3198,286,0 1/1:0,163:163:99:5746,490,0 1/1:0,115:115:99:3777,344,0 1/1:0,81:81:99:2725,243,0 1/1:0,92:92:99:3095,277,0 1/1:0,81:81:99:2814,244,0 1/1:0,55:55:99:1908,165,0 1/1:1,119:120:99:4176,358,0 1/1:0,86:86:99:2973,259,0 1/1:0,132:132:99:4631,397,0 1/1:0,88:88:99:3003,264,0 1/1:0,147:147:99:5035,441,0 1/1:0,87:87:99:3064,261,0 1/1:0,85:85:99:3016,256,0 1/1:0,77:77:99:2667,232,0 1/1:0,87:87:99:3059,262,0 1/1:0,106:106:99:3642,318,0 1/1:0,82:82:99:2751,246,0 1/1:0,106:106:99:3646,319,0 1/1:0,55:55:99:2032,165,0 1/1:0,77:77:99:2688,231,0 1/1:0,67:67:99:2294,201,0 1/1:0,90:90:99:3341,271,0 1/1:0,87:87:99:2991,261,0 1/1:0,150:150:99:5329,451,0 1/1:0,69:69:99:2368,207,0 1/1:0,51:51:99:1769,153,0 1/1:0,82:82:99:2708,245,0 1/1:0,142:142:99:4931,427,0 1/1:0,63:63:99:2077,189,0 1/1:0,48:48:99:1545,144,0 1/1:0,90:90:99:3139,271,0 1/1:0,52:52:99:1815,156,0 1/1:0,66:66:99:2132,198,0 1/1:0,49:49:99:1627,147,0 1/1:0,56:56:99:1992,168,0 1/1:0,83:83:99:2882,250,0 1/1:0,52:52:99:1817,156,0 1/1:0,87:87:99:3118,261,0 +20 13029790 rs6078899 C T 354389.00 PASS HWP=0.0015;AC=55;culprit=FS;MQ0=0;ReadPosRankSum=-0.308;AN=200;InbreedingCoeff=0.1108;AF=0.286;GQ_STDDEV=342.72;FS=5.109;DP=34283;GQ_MEAN=276.21;POSITIVE_TRAIN_SITE;VQSLOD=3.06;ClippingRankSum=0.198;BaseQRankSum=-3.321;MLEAF=0.286;MLEAC=498;MQ=59.7;QD=16.92;DB;MQRankSum=0.014;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:25,22:47:99:602,0,784 0/1:28,18:46:99:458,0,872 0/0:30,0:30:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/1:36,30:66:99:801,0,1148 0/1:22,20:42:99:538,0,619 0/0:28,0:28:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:31,0:31:63:0,63,945 1/1:0,51:51:99:1761,153,0 1/1:0,45:45:99:1528,135,0 0/0:35,0:35:87:0,87,1305 1/1:0,53:53:99:1808,159,0 0/0:22,0:22:60:0,60,900 1/1:0,56:56:99:1893,168,0 0/0:25,0:25:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:31,0:31:63:0,63,945 0/1:33,31:64:99:911,0,1001 0/0:26,0:26:60:0,60,900 0/1:45,44:89:99:1212,0,1324 0/0:34,0:34:78:0,78,1170 0/0:28,0:28:63:0,63,945 0/1:45,31:76:99:788,0,1456 0/1:23,14:37:99:358,0,771 0/1:23,20:43:99:547,0,752 0/0:22,0:22:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:43,0:43:99:0,99,1485 0/0:35,0:35:84:0,84,1260 0/0:47,0:47:93:0,93,1395 0/0:31,0:31:72:0,72,1080 0/0:29,0:29:63:0,63,945 0/1:29,28:57:99:786,0,854 0/0:26,0:26:60:0,60,900 0/1:55,46:101:99:1380,0,1724 0/1:28,28:56:99:800,0,965 0/1:34,32:66:99:916,0,1051 1/1:0,64:64:99:2291,193,0 0/1:36,34:70:99:997,0,1178 0/0:31,0:31:72:0,72,1080 0/0:39,0:39:75:0,75,1125 0/0:36,0:36:87:0,87,1305 0/0:43,0:43:99:0,99,1485 0/1:29,30:59:99:896,0,998 0/0:28,0:28:60:0,60,900 0/1:34,32:66:99:948,0,1103 0/0:31,0:31:75:0,75,1125 0/1:41,29:70:99:845,0,1355 0/1:30,23:53:99:599,0,1010 0/0:28,0:28:63:0,63,945 0/1:35,32:67:99:879,0,1191 0/1:51,37:88:99:1057,0,1690 0/0:32,0:32:78:0,78,1170 0/0:36,0:36:82:0,82,1440 0/0:28,0:28:60:0,60,900 0/1:34,30:64:99:797,0,1098 0/0:29,0:29:63:0,63,945 0/0:34,0:34:72:0,72,1080 0/0:35,0:35:81:0,81,1215 1/1:0,49:49:99:1734,147,0 1/1:0,57:57:99:1992,171,0 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/1:38,39:77:99:1127,0,1391 0/1:31,22:53:99:607,0,1124 1/1:3,93:96:99:3182,279,0 0/1:28,35:63:99:979,0,938 0/0:29,0:29:63:0,63,945 0/1:28,18:46:99:495,0,959 0/0:24,0:24:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:27,21:48:99:589,0,906 0/0:28,0:28:63:0,63,945 1/1:0,63:63:99:2140,189,0 0/1:53,44:97:99:1237,0,1908 0/1:23,17:40:99:452,0,818 0/0:12,0:12:24:0,24,360 0/1:30,30:60:99:802,0,853 1/1:0,94:94:99:3233,283,0 0/0:28,0:28:60:0,60,900 0/1:19,7:26:99:139,0,691 0/0:27,0:27:60:0,60,900 0/0:25,0:25:61:0,61,945 0/1:16,27:43:99:796,0,435 0/0:30,0:30:72:0,72,1080 0/1:18,17:35:99:482,0,557 0/1:30,39:69:99:1157,0,927 0/1:24,12:36:99:299,0,865 0/1:30,28:58:99:768,0,1046 +20 13029862 rs919604 C T 500169.00 PASS HWP=0.0027;AC=198;culprit=MQ;MQ0=0;ReadPosRankSum=0.406;AN=198;InbreedingCoeff=0.0924;AF=0.991;GQ_STDDEV=40.75;FS=5.057;DP=13764;GQ_MEAN=49.89;POSITIVE_TRAIN_SITE;VQSLOD=4.05;ClippingRankSum=0.406;BaseQRankSum=-1.537;MLEAF=0.992;MLEAC=1703;MQ=60.0;QD=26.28;DB;MQRankSum=0.406;CCC=1716;NCC=12 GT:AD:DP:GQ:PL 1/1:0,23:23:69:859,69,0 1/1:0,18:18:54:691,54,0 1/1:0,11:11:33:379,33,0 1/1:0,27:27:81:1017,81,0 1/1:0,17:17:51:640,51,0 1/1:0,19:19:57:710,57,0 1/1:0,17:17:51:646,51,0 1/1:0,11:11:33:392,33,0 1/1:0,22:22:66:832,66,0 1/1:0,14:14:42:516,42,0 1/1:0,13:13:39:506,39,0 1/1:0,10:10:30:324,30,0 1/1:0,14:14:42:523,42,0 1/1:0,13:13:39:486,39,0 1/1:0,39:39:99:1413,117,0 1/1:0,18:18:54:680,54,0 1/1:0,10:10:30:384,30,0 1/1:0,9:9:27:335,27,0 1/1:0,16:16:48:579,48,0 1/1:0,16:16:48:600,48,0 1/1:0,17:17:51:621,51,0 1/1:0,14:14:42:533,42,0 1/1:0,10:10:30:379,30,0 1/1:0,24:24:72:924,72,0 1/1:0,13:13:39:493,39,0 1/1:0,34:34:99:1269,102,0 1/1:0,27:27:81:1004,81,0 1/1:0,31:31:93:1151,93,0 1/1:0,4:4:12:148,12,0 1/1:0,9:9:27:321,27,0 1/1:0,8:8:24:286,24,0 1/1:0,13:13:39:504,39,0 1/1:0,44:44:99:1620,132,0 1/1:0,33:33:99:1241,99,0 1/1:0,45:45:99:1655,135,0 1/1:0,6:6:18:229,18,0 1/1:0,9:9:27:343,27,0 1/1:0,18:18:54:677,54,0 1/1:0,21:21:63:766,63,0 1/1:0,40:40:99:1452,120,0 1/1:0,21:21:63:757,63,0 1/1:0,36:36:99:1350,108,0 1/1:0,18:18:54:677,54,0 1/1:0,31:31:93:1184,93,0 1/1:0,30:30:90:1086,90,0 1/1:0,35:35:99:1311,105,0 1/1:0,36:36:99:1397,108,0 1/1:0,43:43:99:1613,129,0 1/1:0,14:14:42:542,42,0 1/1:0,20:20:60:761,60,0 1/1:0,39:39:99:1441,117,0 1/1:0,24:24:72:921,72,0 1/1:0,24:24:72:846,72,0 1/1:0,20:20:60:745,60,0 1/1:0,23:23:69:868,69,0 1/1:0,20:20:60:719,60,0 1/1:0,37:37:99:1393,111,0 1/1:0,31:31:93:1204,93,0 1/1:0,32:32:96:1221,96,0 1/1:0,28:28:84:1070,84,0 1/1:0,38:38:99:1385,114,0 1/1:0,27:27:81:1003,81,0 1/1:0,33:33:99:1222,99,0 1/1:0,35:35:99:1337,105,0 1/1:0,26:26:78:959,78,0 1/1:0,14:14:42:532,42,0 1/1:0,16:16:48:617,48,0 1/1:0,6:6:18:227,18,0 1/1:0,22:22:66:839,66,0 1/1:0,17:17:51:631,51,0 1/1:0,20:20:60:777,60,0 1/1:0,16:16:48:596,48,0 1/1:0,31:31:93:1153,93,0 1/1:0,16:16:48:587,48,0 1/1:0,16:16:48:618,48,0 1/1:0,13:13:39:492,39,0 1/1:0,18:18:54:672,54,0 1/1:0,12:12:36:443,36,0 1/1:0,15:15:45:580,45,0 1/1:0,9:9:27:350,27,0 1/1:0,11:11:33:413,33,0 1/1:0,18:18:54:668,54,0 1/1:0,9:9:27:345,27,0 1/1:0,28:28:84:1061,84,0 1/1:0,16:16:48:602,48,0 1/1:0,34:34:99:1293,102,0 1/1:0,8:8:24:299,24,0 1/1:0,11:11:33:416,33,0 1/1:0,16:16:48:609,48,0 1/1:0,33:33:99:1255,99,0 1/1:0,14:14:42:540,42,0 ./.:2,0:2:.:. 1/1:0,11:11:33:408,33,0 1/1:0,11:11:33:422,33,0 1/1:0,11:11:33:415,33,0 1/1:0,7:7:21:255,21,0 1/1:0,13:13:39:491,39,0 1/1:0,20:20:60:758,60,0 1/1:0,14:14:42:532,42,0 1/1:0,26:26:78:963,78,0 +20 13029920 rs934335 C G 181727.00 PASS HWP=0.0;AC=172;culprit=MQ;MQ0=0;ReadPosRankSum=0.0;AN=172;InbreedingCoeff=0.1292;AF=0.992;GQ_STDDEV=18.66;FS=0.0;DP=4907;GQ_MEAN=24.56;POSITIVE_TRAIN_SITE;VQSLOD=6.1;ClippingRankSum=0.8;BaseQRankSum=0.0;MLEAF=0.995;MLEAC=1170;MQ=60.0;QD=30.19;DB;MQRankSum=0.101;CCC=1176;NCC=282 GT:AD:DP:GQ:PL 1/1:0,6:6:18:234,18,0 1/1:0,4:4:12:159,12,0 1/1:0,4:4:12:163,12,0 1/1:0,12:12:36:479,36,0 1/1:0,4:4:12:149,12,0 1/1:0,6:6:18:232,18,0 1/1:0,6:6:18:242,18,0 1/1:0,3:3:9:119,9,0 1/1:0,9:9:27:374,27,0 ./.:1,0:1:.:. 1/1:0,3:3:9:133,9,0 1/1:0,5:5:15:188,15,0 1/1:0,6:6:18:229,18,0 1/1:0,5:5:15:202,15,0 1/1:0,17:17:51:637,51,0 1/1:0,4:4:12:160,12,0 1/1:0,4:4:12:147,12,0 1/1:0,4:4:12:154,12,0 1/1:0,3:3:9:112,9,0 1/1:0,7:7:21:270,21,0 ./.:0,0:0:.:. 1/1:0,10:10:30:389,30,0 ./.:2,0:2:.:. 1/1:0,15:15:45:529,45,0 1/1:0,17:17:51:648,51,0 1/1:0,18:18:54:676,54,0 1/1:0,9:9:27:318,27,0 1/1:0,18:18:54:678,54,0 1/1:0,4:4:12:170,12,0 1/1:0,3:3:9:114,9,0 ./.:0,0:0:.:. ./.:2,0:2:.:. 1/1:0,14:14:42:576,42,0 1/1:0,11:11:33:443,33,0 1/1:0,21:21:63:786,63,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,15:15:45:521,45,0 1/1:0,16:16:48:595,48,0 1/1:0,8:8:24:322,24,0 1/1:0,13:13:39:513,39,0 1/1:0,5:5:15:173,15,0 1/1:0,15:15:45:573,45,0 1/1:0,15:15:45:575,45,0 1/1:0,18:18:54:704,54,0 1/1:0,14:14:42:546,42,0 1/1:0,15:15:45:579,45,0 1/1:0,8:8:24:331,24,0 1/1:0,4:4:12:165,12,0 1/1:0,21:21:63:826,63,0 1/1:0,16:16:48:609,48,0 1/1:0,11:11:33:428,33,0 1/1:0,3:3:9:129,9,0 1/1:0,10:10:30:421,30,0 1/1:0,11:11:33:398,33,0 1/1:0,29:29:87:1098,87,0 1/1:0,14:14:42:559,42,0 1/1:0,13:13:39:514,39,0 1/1:0,7:7:21:291,21,0 1/1:0,20:20:60:736,60,0 1/1:0,16:16:48:619,48,0 1/1:0,11:11:33:451,33,0 1/1:0,13:13:39:514,39,0 1/1:0,21:21:63:715,63,0 1/1:0,6:6:18:241,18,0 ./.:0,0:0:.:. 1/1:0,3:3:9:132,9,0 1/1:0,7:7:21:296,21,0 ./.:0,0:0:.:. 1/1:0,8:8:24:307,24,0 1/1:0,5:5:15:215,15,0 1/1:0,11:11:33:462,33,0 1/1:0,5:5:15:203,15,0 1/1:0,8:8:24:336,24,0 1/1:0,5:5:15:210,15,0 1/1:0,3:3:9:124,9,0 1/1:0,7:7:21:305,21,0 1/1:0,8:8:24:335,24,0 1/1:0,4:4:12:169,12,0 ./.:2,0:2:.:. 1/1:0,7:7:21:300,21,0 1/1:0,4:4:12:161,12,0 1/1:0,11:11:33:459,33,0 1/1:0,4:4:12:165,12,0 1/1:0,7:7:21:291,21,0 ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,4:4:12:156,12,0 1/1:0,11:11:33:446,33,0 1/1:0,3:3:9:131,9,0 1/1:0,5:5:15:178,15,0 1/1:0,3:3:9:130,9,0 1/1:0,3:3:9:128,9,0 1/1:0,3:3:9:114,9,0 ./.:2,0:2:.:. 1/1:0,3:3:9:124,9,0 1/1:0,6:6:18:257,18,0 1/1:0,4:4:12:154,12,0 1/1:0,6:6:18:252,18,0 +20 13052882 rs148799627 C A 6269.32 PASS HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.387;AN=200;InbreedingCoeff=-0.0023;AF=0.002299;GQ_STDDEV=108.74;FS=5.382;DP=75904;GQ_MEAN=124.43;POSITIVE_TRAIN_SITE;VQSLOD=3.39;ClippingRankSum=0.27;BaseQRankSum=-2.955;MLEAF=0.002299;MLEAC=4;MQ=59.87;QD=13.17;DB;MQRankSum=1.15;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:60,0:60:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/1:73,55:128:99:1547,0,2230 0/0:108,0:108:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:123,0:123:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/1:49,50:99:99:1499,0,1417 0/0:162,0:162:99:0,120,1800 0/0:185,0:185:99:0,120,1800 0/0:156,0:156:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:146,0:146:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:114,0:114:99:0,120,1800 0/0:155,0:155:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:127,0:127:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:126,0:126:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:139,0:139:99:0,120,1800 0/0:142,0:142:99:0,120,1800 0/0:130,0:130:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:166,0:166:99:0,120,1800 0/0:128,0:128:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:134,0:134:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:120,0:120:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:147,0:147:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:45,0:45:99:0,114,1776 0/0:48,0:48:99:0,113,1559 0/0:109,0:109:99:0,120,1800 0/0:155,0:155:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:78,0:78:99:0,120,1800 +20 13052985 . C A 294.69 VQSRTrancheSNP99.60to99.80 NEGATIVE_TRAIN_SITE;HWP=1.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=-0.418;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=11.06;FS=2.7;DP=76435;GQ_MEAN=117.98;VQSLOD=-2.237;ClippingRankSum=1.17;BaseQRankSum=-2.419;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=1.25;MQRankSum=-1.011;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:60,0:60:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:136,0:136:99:0,120,1800 0/0:108,0:108:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:123,0:123:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:162,0:162:99:0,120,1800 0/0:185,0:185:99:0,120,1800 0/0:156,0:156:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:146,0:146:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:114,0:114:99:0,120,1800 0/0:155,0:155:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:127,0:127:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:126,0:126:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:139,0:139:99:0,120,1800 0/0:142,0:142:99:0,120,1800 0/0:130,0:130:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:166,0:166:99:0,120,1800 0/0:128,0:128:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/1:205,31:236:99:345,0,6477 0/0:50,0:50:99:0,120,1800 0/0:134,0:134:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:120,0:120:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:147,0:147:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:45,0:45:99:0,114,1776 0/0:48,0:48:99:0,113,1559 0/0:109,0:109:99:0,120,1800 0/0:155,0:155:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:78,0:78:99:0,120,1800 +20 13053018 rs243887 T G 7334210.00 PASS HWP=1.0E-4;AC=146;culprit=FS;MQ0=0;ReadPosRankSum=0.381;AN=200;InbreedingCoeff=0.1341;AF=0.755;GQ_STDDEV=1826.35;FS=0.527;DP=270962;GQ_MEAN=2036.53;POSITIVE_TRAIN_SITE;VQSLOD=4.5;ClippingRankSum=0.225;BaseQRankSum=2.2;MLEAF=0.755;MLEAC=1313;MQ=59.61;QD=27.81;DB;MQRankSum=0.133;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:140,163:303:99:4291,0,3769 0/1:136,145:281:99:3994,0,3673 1/1:4,258:262:99:9209,775,0 1/1:10,307:317:99:10320,886,0 1/1:0,351:351:99:11757,1053,0 1/1:0,357:357:99:12129,1072,0 0/1:169,176:345:99:4983,0,4785 0/1:124,123:247:99:3247,0,3474 1/1:9,388:397:99:13824,1166,0 1/1:2,277:279:99:9539,820,0 1/1:0,285:285:99:9973,855,0 1/1:0,288:288:99:13392,987,0 0/0:87,0:87:99:0,120,1800 0/0:69,0:69:99:0,120,1800 1/1:1,142:143:99:4879,393,0 0/0:91,0:91:99:0,120,1800 1/1:0,271:271:99:8891,814,0 0/0:93,0:93:99:0,120,1800 1/1:0,281:281:99:9308,844,0 1/1:0,384:384:99:17595,1290,0 1/1:0,304:304:99:12268,974,0 1/1:0,379:379:99:12525,1138,0 0/1:177,155:332:99:4201,0,4964 1/1:0,360:360:99:13445,1081,0 0/1:177,200:377:99:8824,0,10248 1/1:0,341:341:99:11995,1024,0 1/1:1,358:359:99:12361,1068,0 0/1:137,146:283:99:4316,0,4031 0/1:189,169:358:99:5002,0,5263 0/1:236,178:414:99:5109,0,6222 1/1:0,362:362:99:12639,1086,0 1/1:0,371:371:99:12370,1114,0 1/1:0,354:354:99:13224,1062,0 1/1:0,358:358:99:14304,1076,0 1/1:0,337:337:99:12424,1011,0 1/1:0,364:364:99:11052,1091,0 1/1:0,334:334:99:11328,1003,0 0/1:162,151:313:99:4224,0,4428 1/1:0,321:321:99:11196,961,0 0/1:164,167:331:99:4810,0,4838 0/1:158,114:272:99:3533,0,4604 0/1:162,180:342:99:5450,0,4730 0/0:91,0:91:99:0,120,1800 0/1:160,169:329:99:5216,0,4617 1/1:0,318:318:99:11620,955,0 0/1:149,164:313:99:5088,0,4215 1/1:0,381:381:99:13502,1144,0 1/1:2,336:338:99:12176,979,0 0/1:197,169:366:99:5219,0,5892 1/1:0,348:348:99:12768,1046,0 0/1:182,190:372:99:5625,0,5222 1/1:0,327:327:99:11571,981,0 0/1:173,159:332:99:4566,0,4830 0/1:220,175:395:99:5323,0,6236 1/1:1,361:362:99:13337,1085,0 0/1:176,164:340:99:4808,0,5008 0/1:159,156:315:99:4685,0,4789 1/1:0,325:325:99:11893,976,0 1/1:1,333:334:99:11899,993,0 1/1:0,359:359:99:15476,1172,0 0/1:171,180:351:99:5393,0,4966 1/1:0,357:357:99:12514,1072,0 1/1:0,363:363:99:14482,1092,0 1/1:1,319:320:99:11355,926,0 0/0:105,0:105:99:0,120,1800 0/0:93,0:93:99:0,120,1800 1/1:0,243:243:99:8546,730,0 1/1:0,254:254:99:9249,763,0 0/1:158,177:335:99:5709,0,4777 0/1:153,151:304:99:4409,0,4143 0/0:120,0:120:99:0,120,1800 0/1:211,163:374:99:4932,0,6026 1/1:10,343:353:99:12973,1031,0 0/1:161,158:319:99:4973,0,4469 1/1:2,358:360:99:12897,1039,0 1/1:0,270:270:99:9643,811,0 1/1:0,385:385:99:13692,1156,0 1/1:0,319:319:99:11629,959,0 1/1:0,369:369:99:13282,1108,0 1/1:1,382:383:99:13820,1147,0 1/1:1,265:266:99:9505,795,0 1/1:0,262:262:99:9179,786,0 0/1:132,119:251:99:3544,0,3717 1/1:2,383:385:99:14015,1144,0 0/1:174,180:354:99:5335,0,4745 1/1:1,343:344:99:17215,1241,0 0/1:159,149:308:99:4218,0,4145 1/1:0,318:318:99:10705,954,0 0/1:170,154:324:99:6151,0,10013 0/0:155,0:155:99:0,120,1800 1/1:0,340:340:99:11147,1020,0 0/1:161,158:319:99:4180,0,4145 1/1:0,352:352:99:12631,1057,0 1/1:0,258:258:99:9353,775,0 0/1:172,174:346:99:4686,0,4371 1/1:1,269:270:99:8420,801,0 0/1:146,155:301:99:4514,0,3934 0/1:185,173:358:99:5205,0,5310 0/1:126,119:245:99:3629,0,3512 0/1:209,172:381:99:4961,0,5823 +20 13053035 rs243888 A G 5686740.00 PASS HWP=0.0345;AC=125;culprit=FS;MQ0=0;ReadPosRankSum=0.199;AN=200;InbreedingCoeff=0.0739;AF=0.665;GQ_STDDEV=1840.46;FS=0.564;DP=238637;GQ_MEAN=2125.55;POSITIVE_TRAIN_SITE;VQSLOD=4.35;ClippingRankSum=-0.03;BaseQRankSum=0.079;MLEAF=0.665;MLEAC=1157;MQ=59.61;QD=24.96;DB;MQRankSum=0.087;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:128,133:261:99:3576,0,3564 0/1:135,122:257:99:3389,0,3730 1/1:3,229:232:99:7842,679,0 1/1:7,274:281:99:9297,822,0 1/1:0,293:293:99:9988,880,0 1/1:0,311:311:99:10616,933,0 0/1:158,149:307:99:4448,0,4648 0/1:117,106:223:99:2785,0,3345 1/1:8,334:342:99:11887,1004,0 1/1:3,263:266:99:8661,777,0 1/1:6,247:253:99:8546,724,0 1/1:0,265:265:99:13392,987,0 0/0:87,0:87:99:0,120,1800 0/0:69,0:69:99:0,120,1800 1/1:1,137:138:99:4485,376,0 0/0:91,0:91:99:0,120,1800 0/1:120,123:243:99:3284,0,3346 0/0:93,0:93:99:0,120,1800 1/1:0,239:239:99:7910,717,0 1/1:0,334:334:99:17595,1290,0 0/1:138,127:265:99:3500,0,4020 0/1:177,162:339:99:4485,0,4993 0/1:163,138:301:99:3711,0,4661 1/1:2,334:336:99:12141,1000,0 0/1:162,199:361:99:8824,0,10248 0/1:162,154:316:99:4563,0,4995 1/1:0,323:323:99:10883,969,0 0/1:133,145:278:99:4180,0,4125 0/1:171,172:343:99:5088,0,5106 0/1:226,174:400:99:4860,0,6466 1/1:0,327:327:99:11261,982,0 1/1:2,313:315:99:10811,917,0 0/1:192,150:342:99:4398,0,5897 1/1:1,352:353:99:13156,1023,0 1/1:0,333:333:99:11991,996,0 0/1:152,158:310:99:4053,0,3864 1/1:2,283:285:99:9665,850,0 0/0:106,0:106:99:0,120,1800 1/1:0,301:301:99:10285,902,0 0/1:151,158:309:99:4593,0,4516 0/1:138,109:247:99:3118,0,4232 0/0:101,0:101:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/1:141,150:291:99:4396,0,4261 1/1:1,290:291:99:10105,831,0 0/0:149,0:149:99:0,120,1800 1/1:0,319:319:99:11404,957,0 1/1:0,318:318:99:11387,953,0 0/1:179,152:331:99:4830,0,5703 0/1:172,142:314:99:4348,0,5413 0/1:169,168:337:99:4898,0,5302 0/1:144,144:288:99:4275,0,4383 0/1:152,143:295:99:4065,0,4576 0/1:201,149:350:99:4338,0,5925 0/1:190,157:347:99:4625,0,5794 0/1:164,149:313:99:4120,0,4897 0/1:147,150:297:99:4357,0,4472 1/1:0,303:303:99:10926,909,0 0/1:183,128:311:99:3436,0,5800 0/1:170,159:329:99:5047,0,5387 0/1:161,166:327:99:4709,0,5044 1/1:1,308:309:99:10509,885,0 1/1:0,356:356:99:13596,1070,0 1/1:0,297:297:99:10425,889,0 0/0:105,0:105:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:60,0:60:99:0,120,1800 1/1:0,242:242:99:8535,726,0 0/0:151,0:151:99:0,120,1800 0/1:134,136:270:99:3888,0,3840 0/0:120,0:120:99:0,120,1800 0/1:194,156:350:99:4567,0,5815 0/1:176,169:345:99:5216,0,5055 0/1:128,147:275:99:4425,0,3815 0/1:178,144:322:99:4368,0,5222 0/1:146,109:255:99:3150,0,4197 1/1:0,340:340:99:11943,1020,0 1/1:1,276:277:99:9967,789,0 1/1:0,331:331:99:11786,994,0 0/1:190,169:359:99:4577,0,5703 1/1:1,238:239:99:8674,679,0 1/1:0,251:251:99:8610,753,0 0/1:132,105:237:99:3180,0,3987 1/1:0,319:319:99:11724,959,0 0/1:159,150:309:99:4451,0,4638 1/1:1,326:327:99:17210,1241,0 0/1:139,133:272:99:3707,0,3902 1/1:0,271:271:99:9021,813,0 0/1:156,139:295:99:6151,0,10013 0/0:155,0:155:99:0,120,1800 1/1:1,288:289:99:9479,858,0 0/1:127,127:254:99:3494,0,3680 1/1:0,305:305:99:10882,915,0 1/1:0,247:247:99:8772,741,0 0/1:149,153:302:99:3996,0,4196 1/1:1,228:229:99:7443,680,0 0/1:132,141:273:99:4164,0,3803 0/1:166,154:320:99:4689,0,5063 0/1:115,94:209:99:3007,0,3349 0/1:189,148:337:99:4292,0,5789 +20 13071816 rs6109692 C T 200692.00 PASS HWP=1.0;AC=27;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.609;AN=200;InbreedingCoeff=0.0044;AF=0.081;GQ_STDDEV=488.69;FS=1.958;DP=49555;GQ_MEAN=277.73;POSITIVE_TRAIN_SITE;VQSLOD=5.1;ClippingRankSum=0.261;BaseQRankSum=2.51;MLEAF=0.081;MLEAC=141;MQ=59.7;QD=14.01;DB;MQRankSum=0.247;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:58,39:97:99:1103,0,1663 0/0:35,0:35:75:0,75,1125 0/1:40,36:76:99:1074,0,1166 0/0:41,0:41:99:0,99,1485 0/1:53,46:99:99:1340,0,1497 0/1:62,38:100:99:1085,0,1738 0/1:67,41:108:99:1120,0,1894 0/0:27,0:27:60:0,60,900 0/1:46,53:99:99:1630,0,1248 0/0:43,0:43:99:0,99,1485 0/1:48,49:97:99:1501,0,1422 0/1:41,44:85:99:1286,0,1123 0/0:37,0:37:90:0,90,1350 0/0:39,0:39:90:0,90,1350 0/1:33,32:65:99:896,0,854 0/0:40,0:40:69:0,69,1035 0/0:70,0:70:99:0,120,1800 0/0:43,0:43:90:0,90,1350 0/0:37,0:37:78:0,78,1170 0/1:71,60:131:99:1767,0,1928 0/0:85,0:85:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:99:0,105,1575 0/0:39,0:39:96:0,96,1440 0/0:44,0:44:96:0,96,1440 0/0:34,0:34:75:0,75,1125 0/1:55,49:104:99:1323,0,1483 0/1:47,42:89:99:1183,0,1439 0/0:107,0:107:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/1:80,89:169:99:2733,0,2241 0/0:64,0:64:99:0,120,1800 0/1:46,37:83:99:1031,0,1377 0/0:58,0:58:99:0,120,1800 1/1:0,110:110:99:3852,329,0 0/0:49,0:49:99:0,111,1665 0/0:45,0:45:99:0,102,1530 0/0:72,0:72:99:0,120,1800 0/0:44,0:44:87:0,87,1305 0/0:62,0:62:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:42,0:42:72:0,72,1305 0/1:50,58:108:99:1749,0,1312 0/0:38,0:38:81:0,81,1215 0/0:30,0:30:63:0,63,945 0/1:78,48:126:99:1358,0,2274 0/0:45,0:45:99:0,105,1575 0/0:93,0:93:99:0,120,1800 0/0:56,0:56:99:0,111,1665 0/0:89,0:89:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:46,0:46:99:0,99,1485 0/0:30,0:30:69:0,69,1035 0/0:65,0:65:99:0,120,1800 0/1:57,62:119:99:1847,0,1550 0/0:40,0:40:93:0,93,1395 0/0:41,0:41:93:0,93,1395 0/0:31,0:31:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:116,0:116:99:0,120,1800 0/0:45,0:45:99:0,102,1530 0/0:43,0:43:99:0,105,1575 0/0:30,0:30:60:0,60,900 0/1:103,72:175:99:1992,0,2826 0/0:25,0:25:60:0,60,900 0/0:53,0:53:99:0,120,1800 0/1:30,32:62:99:924,0,888 0/0:50,0:50:99:0,105,1575 0/0:33,0:33:69:0,69,1035 0/0:45,0:45:90:0,90,1350 0/1:46,53:99:99:1637,0,1313 0/0:25,0:25:60:0,60,900 0/0:42,0:42:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:33,0:33:72:0,72,1080 0/0:28,0:28:66:0,66,990 0/0:47,0:47:99:0,111,1665 0/0:27,0:27:60:0,60,900 0/1:52,45:97:99:1164,0,1502 0/0:42,0:42:96:0,96,1440 0/0:50,0:50:99:0,114,1710 0/1:68,39:107:99:1045,0,1830 0/0:35,0:35:75:0,75,1125 0/1:46,41:87:99:1191,0,1379 0/0:28,0:28:69:0,69,1035 0/0:34,0:34:60:0,60,900 0/1:35,40:75:99:1036,0,943 0/0:28,0:28:60:0,60,900 0/0:33,0:33:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/1:71,44:115:99:1258,0,2034 +20 13071871 rs243874 C A 384560.00 PASS HWP=0.4201;AC=63;culprit=FS;MQ0=0;ReadPosRankSum=0.31;AN=200;InbreedingCoeff=0.0296;AF=0.269;GQ_STDDEV=377.62;FS=3.346;DP=42910;GQ_MEAN=339.52;POSITIVE_TRAIN_SITE;VQSLOD=4.03;ClippingRankSum=-0.083;BaseQRankSum=-3.498;MLEAF=0.269;MLEAC=468;MQ=59.68;QD=15.97;DB;MQRankSum=0.161;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:39,22:61:99:602,0,1250 0/0:35,0:35:75:0,75,1125 0/1:19,18:37:99:504,0,576 0/1:16,25:41:99:760,0,496 1/1:0,52:52:99:1845,156,0 0/1:40,27:67:99:767,0,1321 0/1:38,21:59:99:599,0,1320 0/0:27,0:27:60:0,60,900 0/1:26,30:56:99:865,0,955 0/1:21,19:40:99:588,0,648 1/1:0,48:48:99:1679,144,0 0/1:30,26:56:99:739,0,920 0/0:37,0:37:90:0,90,1350 0/0:39,0:39:90:0,90,1350 0/1:27,23:50:99:670,0,831 0/0:40,0:40:69:0,69,1035 0/1:35,32:67:99:969,0,1029 0/0:43,0:43:90:0,90,1350 0/0:37,0:37:78:0,78,1170 1/1:0,85:85:99:3050,256,0 0/1:56,26:82:99:710,0,1733 1/1:0,55:55:99:2021,165,0 0/0:60,0:60:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/1:28,27:55:99:788,0,885 0/0:45,0:45:99:0,105,1575 0/0:39,0:39:96:0,96,1440 0/0:44,0:44:96:0,96,1440 0/0:34,0:34:75:0,75,1125 0/1:26,27:53:99:753,0,913 1/1:1,60:61:99:2035,173,0 1/1:0,102:102:99:3615,307,0 0/1:58,47:105:99:1311,0,2063 1/1:0,91:91:99:3208,273,0 0/1:40,22:62:99:545,0,1093 0/1:31,18:49:99:455,0,1023 0/1:35,22:57:99:653,0,1075 1/1:0,70:70:99:2450,210,0 0/0:49,0:49:99:0,111,1665 0/0:45,0:45:99:0,102,1530 0/1:31,38:69:99:1148,0,1046 0/0:44,0:44:87:0,87,1305 0/1:33,28:61:99:863,0,1116 0/1:39,37:76:99:1080,0,1255 0/1:56,49:105:99:1488,0,1902 0/0:48,0:48:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/1:57,47:104:99:1368,0,2001 0/0:42,0:42:72:0,72,1305 1/1:0,51:51:99:1884,153,0 0/0:38,0:38:81:0,81,1215 0/0:30,0:30:63:0,63,945 0/1:41,26:67:99:728,0,1384 0/0:45,0:45:99:0,105,1575 0/1:41,51:92:99:1548,0,1361 0/0:56,0:56:99:0,111,1665 0/1:45,45:90:99:1302,0,1551 0/1:64,50:114:99:1483,0,2450 0/0:46,0:46:99:0,99,1485 0/0:30,0:30:69:0,69,1035 0/0:65,0:65:99:0,120,1800 0/1:35,41:76:99:1201,0,1163 0/0:40,0:40:93:0,93,1395 0/0:41,0:41:93:0,93,1395 1/1:0,29:29:87:980,87,0 0/0:23,0:23:60:0,60,900 0/1:60,54:114:99:1617,0,2046 0/1:25,20:45:99:574,0,930 0/0:43,0:43:99:0,105,1575 0/0:30,0:30:60:0,60,900 1/1:6,70:76:83:2378,83,0 0/0:25,0:25:60:0,60,900 0/1:27,24:51:99:709,0,981 0/1:15,18:33:99:515,0,570 0/1:23,25:48:99:771,0,765 0/0:33,0:33:69:0,69,1035 0/1:27,17:44:99:438,0,1001 1/1:0,38:38:99:1347,114,0 0/0:25,0:25:60:0,60,900 0/1:18,22:40:99:654,0,631 0/0:27,0:27:60:0,60,900 0/0:33,0:33:72:0,72,1080 0/0:28,0:28:66:0,66,990 0/0:47,0:47:99:0,111,1665 0/0:27,0:27:60:0,60,900 0/1:47,22:69:99:576,0,1360 0/0:42,0:42:96:0,96,1440 0/0:50,0:50:99:0,114,1710 0/1:40,23:63:99:531,0,1287 0/0:35,0:35:75:0,75,1125 0/1:28,27:55:99:823,0,1027 0/0:28,0:28:69:0,69,1035 0/0:34,0:34:60:0,60,900 0/1:37,19:56:99:459,0,1066 0/0:28,0:28:60:0,60,900 0/0:33,0:33:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/1:38,30:68:99:804,0,1376 +20 13074103 . G T 30125.70 VQSRTrancheSNP99.95to100.00 HWP=0.0024;AC=26;culprit=FS;MQ0=0;ReadPosRankSum=-2.992;AN=200;InbreedingCoeff=-0.163;AF=0.084;GQ_STDDEV=86.67;FS=123.58;DP=39009;GQ_MEAN=88.36;VQSLOD=-157.6;ClippingRankSum=3.48;BaseQRankSum=-3.071;MLEAF=0.105;MLEAC=183;MQ=59.23;QD=3.58;MQRankSum=0.169;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:43,0:43:96:0,96,1440 0/0:35,0:35:81:0,81,1215 0/0:31,0:31:69:0,69,1035 0/0:41,0:41:99:0,114,1710 0/0:42,0:42:99:0,120,1800 0/0:40,0:40:96:0,96,1440 0/0:48,0:48:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:38,0:38:81:0,81,1215 0/0:38,0:38:96:0,96,1440 0/0:29,0:29:60:0,60,900 0/0:44,0:44:70:0,70,1305 0/0:46,0:46:99:0,108,1665 0/0:42,0:42:99:0,111,1665 0/0:36,0:36:96:0,96,1188 0/0:41,0:41:99:0,120,1800 0/0:38,0:38:78:0,78,1170 0/0:46,0:46:99:0,108,1620 0/0:39,0:39:84:0,84,1260 0/0:68,0:68:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:55,0:55:99:0,111,1665 0/0:69,0:69:0:0,0,1976 0/0:75,0:75:0:0,0,2093 0/0:33,0:33:0:0,0,872 0/1:32,19:51:99:332,0,823 0/1:28,16:44:99:195,0,757 0/0:69,0:69:62:0,62,1800 0/0:67,0:67:18:0,18,1873 0/0:56,0:56:99:0,120,1800 0/0:29,0:29:84:0,84,1094 0/1:30,14:44:99:211,0,956 0/1:48,29:77:99:408,0,1352 0/1:52,24:76:99:187,0,1330 0/0:33,0:33:63:0,63,1211 0/0:27,0:27:81:0,81,1074 0/0:40,0:40:99:0,111,1665 0/1:25,11:36:99:166,0,687 0/0:39,0:39:0:0,0,672 0/0:21,0:21:0:0,0,416 0/0:25,0:25:0:0,0,321 0/1:32,11:43:90:90,0,877 0/1:29,12:41:99:164,0,693 0/1:20,10:30:99:205,0,596 0/1:41,16:57:99:211,0,1078 0/1:23,16:39:99:257,0,612 0/1:38,20:58:99:205,0,856 0/0:68,0:68:0:0,0,1374 0/0:71,0:71:0:0,0,1579 0/0:33,0:33:0:0,0,576 0/1:25,12:37:99:120,0,626 0/0:27,0:27:0:0,0,436 0/1:30,18:48:99:229,0,745 0/0:34,0:34:0:0,0,701 0/1:24,13:37:99:179,0,661 0/1:36,19:55:99:171,0,967 0/0:44,0:44:0:0,0,780 0/1:27,26:53:99:413,0,617 0/0:67,0:67:0:0,0,894 0/0:30,0:30:24:0,24,630 0/0:43,0:43:0:0,0,897 0/1:42,29:71:99:372,0,1126 0/0:41,0:41:0:0,0,447 0/0:36,0:36:0:0,0,418 0/0:51,0:51:99:0,120,1800 0/0:28,0:28:0:0,0,320 0/0:15,0:15:0:0,0,367 0/1:50,23:73:99:235,0,1404 0/0:22,0:22:0:0,0,482 0/1:39,16:55:62:62,0,1142 0/0:31,0:31:0:0,0,598 0/1:63,25:88:99:132,0,1530 0/0:27,0:27:0:0,0,400 0/0:43,0:43:0:0,0,1019 0/0:28,0:28:0:0,0,489 0/0:38,0:38:0:0,0,973 0/0:33,0:33:0:0,0,601 0/0:24,0:24:0:0,0,365 0/1:28,10:38:99:127,0,812 0/0:20,0:20:0:0,0,296 0/0:26,0:26:0:0,0,580 0/1:9,12:21:99:184,0,211 0/1:24,11:35:42:42,0,729 0/0:31,0:31:0:0,0,550 0/1:40,12:52:62:62,0,1182 0/0:32,0:32:78:0,78,1170 0/0:38,0:38:41:0,41,1122 0/0:39,0:39:99:0,99,1485 0/0:59,0:59:0:0,0,1174 0/0:31,0:31:93:0,93,1182 0/0:40,0:40:99:0,102,1530 0/0:32,0:32:0:0,0,515 0/0:20,0:20:0:0,0,440 0/0:44,0:44:99:0,111,1665 0/0:29,0:29:81:0,81,1215 0/0:19,0:19:0:0,0,275 0/0:19,0:19:0:0,0,268 0/1:17,9:26:99:114,0,491 0/0:36,0:36:0:0,0,680 +20 13074125 rs77696068 G A 40457.90 PASS HWP=0.8838;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.556;AN=200;InbreedingCoeff=-0.0314;AF=0.03;GQ_STDDEV=170.45;FS=0.0;DP=37262;GQ_MEAN=129.72;POSITIVE_TRAIN_SITE;VQSLOD=5.37;ClippingRankSum=-0.215;BaseQRankSum=-2.438;MLEAF=0.03;MLEAC=53;MQ=59.63;QD=11.32;DB;MQRankSum=0.566;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:43,0:43:96:0,96,1440 0/0:35,0:35:81:0,81,1215 0/0:31,0:31:69:0,69,1035 0/0:41,0:41:99:0,114,1710 0/0:42,0:42:99:0,120,1800 0/0:40,0:40:96:0,96,1440 0/0:48,0:48:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:38,0:38:81:0,81,1215 0/0:38,0:38:96:0,96,1440 0/0:29,0:29:60:0,60,900 0/0:44,0:44:70:0,70,1305 0/0:46,0:46:99:0,108,1665 0/0:42,0:42:99:0,111,1665 0/1:16,22:38:99:573,0,423 0/0:41,0:41:99:0,120,1800 0/0:38,0:38:78:0,78,1170 0/0:46,0:46:99:0,108,1620 0/0:39,0:39:84:0,84,1260 0/0:68,0:68:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:55,0:55:99:0,111,1665 0/0:60,0:60:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:32,0:32:68:0,68,1127 0/0:34,0:34:77:0,77,1260 0/0:36,0:36:84:0,84,1260 0/0:69,0:69:62:0,62,1800 0/0:59,0:59:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:29,0:29:84:0,84,1094 0/0:37,0:37:93:0,93,1395 0/0:59,0:59:99:0,115,1800 0/0:67,0:67:99:0,120,1800 0/0:33,0:33:63:0,63,1211 0/1:29,37:66:99:874,0,743 0/0:40,0:40:99:0,111,1665 0/0:33,0:33:66:0,66,990 0/0:30,0:30:81:0,81,1051 0/0:25,0:25:72:0,72,1037 0/0:29,0:29:78:0,78,1035 0/0:37,0:37:72:0,72,1204 0/0:30,0:30:64:0,64,1019 0/0:26,0:26:78:0,78,950 0/0:41,0:41:99:0,102,1530 0/0:28,0:28:63:0,63,945 0/0:45,0:45:99:0,105,1518 0/0:53,0:53:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:23,0:23:60:0,60,900 0/0:25,0:25:64:0,64,877 0/0:25,0:25:75:0,75,955 0/0:32,0:32:78:0,78,1215 0/0:40,0:40:90:0,90,1350 0/0:27,0:27:66:0,66,990 0/0:42,0:42:99:0,102,1530 0/0:38,0:38:75:0,75,1125 0/0:35,0:35:87:0,87,1305 0/0:48,0:48:99:0,114,1746 0/0:29,0:29:84:0,84,1260 0/0:39,0:39:99:0,102,1530 0/0:50,0:50:99:0,120,1800 0/0:32,0:32:67:0,67,1125 0/0:28,0:28:78:0,78,967 0/0:51,0:51:99:0,120,1800 0/0:24,0:24:63:0,63,945 0/0:20,0:20:60:0,60,718 0/0:54,0:54:99:0,120,1800 0/0:25,0:25:66:0,66,890 0/0:42,0:42:99:0,108,1620 0/0:26,0:26:66:0,66,990 0/0:65,0:65:99:0,120,1800 0/0:26,0:26:63:0,63,945 0/0:35,0:35:84:0,84,1301 0/0:25,0:25:60:0,60,900 0/0:36,0:36:75:0,75,1125 0/0:28,0:28:65:0,65,990 0/0:25,0:25:60:0,60,900 0/0:36,0:36:84:0,84,1260 0/0:20,0:20:60:0,60,766 0/0:21,0:21:60:0,60,782 0/0:23,0:23:65:0,65,869 0/0:28,0:28:62:0,62,1080 0/0:24,0:24:60:0,60,900 0/0:47,0:47:99:0,117,1755 0/0:32,0:32:78:0,78,1170 0/0:37,0:37:99:0,102,1425 0/0:39,0:39:99:0,99,1485 0/0:59,0:59:99:0,120,1800 0/0:31,0:31:93:0,93,1182 0/0:40,0:40:99:0,102,1530 0/0:28,0:28:63:0,63,945 0/0:28,0:28:69:0,69,1035 0/0:44,0:44:99:0,111,1665 0/0:29,0:29:81:0,81,1215 0/0:21,0:21:62:0,62,823 0/0:20,0:20:60:0,60,687 0/0:22,0:22:60:0,60,836 0/0:35,0:35:80:0,80,1249 +20 13074235 rs708937 G A 1562350.00 PASS HWP=0.7656;AC=187;culprit=QD;MQ0=0;ReadPosRankSum=0.292;AN=200;InbreedingCoeff=0.0258;AF=0.976;GQ_STDDEV=151.88;FS=1.0;DP=42210;GQ_MEAN=171.37;POSITIVE_TRAIN_SITE;VQSLOD=3.42;ClippingRankSum=0.102;BaseQRankSum=-3.433;MLEAF=0.976;MLEAC=1699;MQ=59.41;QD=34.04;DB;MQRankSum=0.411;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,42:42:99:1540,126,0 1/1:0,33:33:99:1209,99,0 1/1:0,30:30:90:1049,90,0 0/1:27,24:51:99:703,0,819 1/1:0,57:57:99:2022,171,0 0/1:22,19:41:99:557,0,697 1/1:0,53:53:99:1973,159,0 1/1:0,43:43:99:1581,129,0 1/1:0,39:39:99:1486,117,0 0/1:25,13:38:99:364,0,808 1/1:0,28:28:84:979,84,0 0/1:22,10:32:99:270,0,750 1/1:0,42:42:99:1594,126,0 1/1:0,45:45:99:1627,135,0 1/1:0,33:33:99:1296,99,0 1/1:0,49:49:99:1859,147,0 1/1:0,37:37:99:1356,111,0 1/1:0,44:44:99:1573,132,0 1/1:0,41:41:99:1523,123,0 1/1:0,80:80:99:3220,241,0 1/1:0,54:54:99:2146,162,0 1/1:0,66:66:99:2636,199,0 1/1:0,54:54:99:1972,162,0 1/1:0,98:98:99:3524,295,0 1/1:0,125:125:99:4705,376,0 1/1:0,43:43:99:1786,135,0 1/1:0,53:53:99:1934,159,0 1/1:0,35:35:99:1263,105,0 1/1:0,67:67:99:2290,201,0 1/1:0,58:58:99:2023,174,0 1/1:0,60:60:99:2033,180,0 1/1:0,44:44:99:1689,135,0 1/1:0,63:63:99:2550,196,0 0/1:57,41:98:99:1179,0,1966 1/1:0,87:87:99:3224,262,0 1/1:0,37:37:99:1279,111,0 1/1:0,45:45:99:1868,138,0 1/1:0,56:56:99:1975,168,0 1/1:0,50:50:99:1823,150,0 1/1:0,72:72:99:2808,220,0 1/1:0,38:38:99:1316,114,0 1/1:0,40:40:99:1575,120,0 1/1:0,48:48:99:2013,150,0 1/1:0,54:54:99:1933,162,0 1/1:0,58:58:99:2682,187,0 1/1:0,60:60:99:2451,190,0 1/1:0,53:53:99:2419,172,0 1/1:0,71:71:99:2953,226,0 1/1:0,63:63:99:2356,190,0 1/1:0,81:81:99:3322,250,0 1/1:0,53:53:99:2064,159,0 1/1:0,39:39:99:1410,117,0 1/1:0,32:32:99:1276,99,0 1/1:0,44:44:99:1562,132,0 1/1:0,75:75:99:2580,226,0 1/1:0,50:50:99:1750,150,0 1/1:0,53:53:99:2142,162,0 1/1:0,67:67:99:2675,202,0 1/1:0,54:54:99:2525,178,0 0/1:32,42:74:99:1619,0,2111 1/1:0,45:45:99:1949,135,0 1/1:0,54:54:99:1961,162,0 1/1:0,84:84:99:3681,253,0 1/1:0,48:48:99:1666,144,0 1/1:0,31:31:96:1275,96,0 1/1:0,47:47:99:1719,141,0 0/0:24,0:24:63:0,63,945 1/1:0,29:29:87:1021,87,0 0/1:41,42:83:99:1226,0,1386 1/1:0,27:27:87:1098,87,0 0/1:21,34:55:99:1040,0,692 1/1:0,38:38:99:1396,114,0 1/1:3,70:73:99:2911,133,0 1/1:0,29:29:87:1167,87,0 1/1:0,42:42:99:1914,135,0 1/1:0,39:39:99:1336,117,0 1/1:0,34:34:99:1442,111,0 1/1:0,29:29:87:1029,87,0 1/1:0,28:28:84:1051,84,0 0/1:22,17:39:99:619,0,1520 1/1:0,27:27:81:1096,81,0 1/1:0,32:32:99:1337,99,0 0/1:11,19:30:99:609,0,368 0/1:14,23:37:99:936,0,847 1/1:0,43:43:99:1654,132,0 1/1:0,73:73:99:2646,220,0 1/1:0,35:35:99:1406,111,0 1/1:0,49:49:99:1984,147,0 1/1:0,39:39:99:1484,117,0 1/1:0,67:67:99:2367,202,0 1/1:0,50:50:99:2010,150,0 1/1:0,44:44:99:1544,132,0 1/1:0,26:26:78:935,78,0 1/1:0,27:27:81:988,81,0 1/1:0,43:43:99:1514,129,0 1/1:0,47:47:99:1821,141,0 1/1:0,33:33:99:1193,99,0 1/1:0,36:36:99:1293,108,0 1/1:0,26:26:78:936,78,0 1/1:0,43:43:99:1748,135,0 +20 13074236 rs145113034 T C 5886.05 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.375;AN=200;InbreedingCoeff=-0.0047;AF=0.004598;GQ_STDDEV=67.9;FS=5.245;DP=31686;GQ_MEAN=83.06;POSITIVE_TRAIN_SITE;VQSLOD=2.93;ClippingRankSum=-0.829;BaseQRankSum=-3.091;MLEAF=0.004598;MLEAC=8;MQ=59.25;QD=15.25;DB;MQRankSum=0.347;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:35,0:35:65:0,65,1228 0/0:32,0:32:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:33,0:33:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:22,0:22:63:0,63,821 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,99,1485 0/0:60,0:60:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:36,0:36:66:0,66,990 0/0:32,0:32:66:0,66,990 0/0:38,0:38:96:0,96,1440 0/0:24,0:24:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:27,0:27:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:32,0:32:78:0,78,1170 0/0:39,0:39:87:0,87,1305 0/0:59,0:59:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:40,0:40:87:0,87,1305 0/0:33,0:33:60:0,60,900 0/0:45,0:45:99:0,99,1485 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:35,0:35:84:0,84,1260 0/0:41,0:41:93:0,93,1395 0/0:31,0:31:81:0,81,1215 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,114,1710 0/0:49,0:49:99:0,108,1620 0/0:68,0:68:99:0,120,1800 0/0:32,0:32:78:0,78,1170 0/0:75,0:75:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:29,0:29:63:0,63,945 0/0:32,0:32:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:33,0:33:63:0,63,1087 0/0:32,0:32:75:0,75,1125 0/0:50,0:50:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:39,0:39:87:0,87,1305 0/0:41,0:41:99:0,102,1530 0/0:77,0:77:99:0,120,1800 0/0:31,0:31:72:0,72,1080 0/0:30,0:30:72:0,72,1080 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:47,0:47:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:50,0:50:99:0,108,1620 0/0:32,0:32:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:38,0:38:84:0,84,1260 0/0:27,0:27:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:35,0:35:81:0,81,1215 0/0:26,0:26:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:33,0:33:75:0,75,1125 0/0:32,0:32:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:29,0:29:63:0,63,945 0/1:24,25:49:99:699,0,745 0/0:29,0:29:63:0,63,945 0/0:32,0:32:63:0,63,945 0/1:22,28:50:99:812,0,628 0/0:33,0:33:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:38,0:38:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:12,0:12:33:0,33,495 0/0:38,0:38:96:0,96,1440 +20 13074237 rs114324835 G T 13192.80 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.301;AN=200;InbreedingCoeff=-0.0134;AF=0.013;GQ_STDDEV=87.96;FS=1.096;DP=31463;GQ_MEAN=89.02;POSITIVE_TRAIN_SITE;VQSLOD=4.71;ClippingRankSum=-0.221;BaseQRankSum=-2.065;MLEAF=0.013;MLEAC=23;MQ=59.73;QD=14.92;DB;MQRankSum=0.437;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:33,0:33:23:0,23,1110 0/0:32,0:32:60:0,60,900 0/0:24,0:24:63:0,63,945 0/1:21,12:33:99:320,0,654 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:22,0:22:63:0,63,821 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,99,1485 0/0:60,0:60:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:36,0:36:66:0,66,990 0/0:32,0:32:66:0,66,990 0/0:38,0:38:96:0,96,1440 0/0:24,0:24:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:27,0:27:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:32,0:32:78:0,78,1170 0/0:39,0:39:87:0,87,1305 0/0:59,0:59:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:40,0:40:87:0,87,1305 0/0:33,0:33:60:0,60,900 0/1:21,25:46:99:822,0,725 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:35,0:35:84:0,84,1260 0/0:41,0:41:93:0,93,1395 0/0:31,0:31:81:0,81,1215 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,114,1710 0/0:49,0:49:99:0,108,1620 0/0:68,0:68:99:0,120,1800 0/0:32,0:32:78:0,78,1170 0/0:75,0:75:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:29,0:29:63:0,63,945 0/0:32,0:32:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:33,0:33:63:0,63,1087 0/0:32,0:32:75:0,75,1125 0/0:50,0:50:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:39,0:39:87:0,87,1305 0/0:41,0:41:99:0,102,1530 0/0:77,0:77:99:0,120,1800 0/0:31,0:31:72:0,72,1080 0/0:30,0:30:72:0,72,1080 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:47,0:47:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:50,0:50:99:0,108,1620 0/0:32,0:32:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:38,0:38:84:0,84,1260 0/0:27,0:27:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:35,0:35:81:0,81,1215 0/0:26,0:26:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:33,0:33:75:0,75,1125 0/0:32,0:32:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:35,0:35:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:38,0:38:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:12,0:12:33:0,33,495 0/0:38,0:38:96:0,96,1440 +20 13074243 rs1011290 T A 404853.00 PASS HWP=0.0764;AC=44;culprit=FS;MQ0=0;ReadPosRankSum=0.36;AN=200;InbreedingCoeff=0.0619;AF=0.315;GQ_STDDEV=290.16;FS=0.0;DP=30116;GQ_MEAN=259.74;POSITIVE_TRAIN_SITE;VQSLOD=5.97;ClippingRankSum=-0.277;BaseQRankSum=-2.276;MLEAF=0.315;MLEAC=548;MQ=59.48;QD=22.13;DB;MQRankSum=0.102;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:20,0:20:51:0,51,765 0/0:13,0:13:30:0,30,450 0/0:32,0:32:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:23,0:23:54:0,54,810 0/0:26,0:26:60:0,60,900 0/0:11,0:11:24:0,24,360 0/0:30,0:30:60:0,60,900 0/0:22,0:22:63:0,63,821 0/1:35,37:72:99:1023,0,1027 0/1:25,23:48:99:626,0,749 0/1:31,28:59:99:816,0,933 0/0:23,0:23:63:0,63,945 0/0:36,0:36:66:0,66,990 0/0:32,0:32:66:0,66,990 0/1:19,19:38:99:564,0,591 0/0:24,0:24:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:27,0:27:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:32,0:32:78:0,78,1170 0/1:22,17:39:99:490,0,616 0/1:29,29:58:99:812,0,793 0/0:38,0:38:87:0,87,1305 0/0:40,0:40:87:0,87,1305 0/0:33,0:33:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/1:33,24:57:99:676,0,1071 0/0:27,0:27:60:0,60,900 0/1:26,11:37:99:257,0,855 0/1:17,25:42:99:782,0,499 0/0:31,0:31:81:0,81,1215 1/1:0,54:54:99:2682,187,0 0/1:28,25:53:99:678,0,840 1/1:0,48:48:99:2419,172,0 0/1:34,33:67:99:907,0,1039 0/0:32,0:32:78:0,78,1170 0/1:37,37:74:99:1119,0,1172 0/1:29,17:46:99:475,0,966 0/0:29,0:29:63:0,63,945 0/1:20,13:33:99:366,0,576 0/0:27,0:27:60:0,60,900 0/0:33,0:33:63:0,63,1087 0/0:32,0:32:75:0,75,1125 0/1:27,23:50:99:657,0,801 0/1:31,26:57:99:771,0,1015 1/1:0,53:53:99:2525,178,0 0/1:29,35:64:99:1619,0,2111 1/1:0,37:37:99:1949,135,0 0/0:41,0:41:99:0,102,1530 1/1:0,75:75:99:3681,253,0 0/0:31,0:31:72:0,72,1080 0/1:17,13:30:99:351,0,512 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:15,0:15:39:0,39,585 0/0:47,0:47:99:0,120,1800 0/1:15,10:25:99:282,0,463 0/0:43,5:48:58:0,58,2349 0/0:32,0:32:60:0,60,900 1/1:3,55:58:99:2918,140,0 0/1:14,13:27:99:377,0,451 1/1:0,37:37:99:1914,135,0 0/0:27,0:27:60:0,60,900 0/1:16,14:30:99:406,0,494 0/0:22,0:22:60:0,60,900 0/1:15,9:24:99:245,0,469 0/1:19,14:33:99:619,0,1520 0/1:14,14:28:99:419,0,417 0/1:7,20:27:99:598,0,175 0/0:26,0:26:66:0,66,990 0/1:10,21:31:99:936,0,847 0/1:16,14:30:99:401,0,452 0/0:32,0:32:60:0,60,900 0/1:14,13:27:99:386,0,422 0/0:35,0:35:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:14,0:14:30:0,30,450 0/0:14,0:14:24:0,24,360 0/0:24,0:24:60:0,60,900 0/1:17,17:34:99:505,0,514 0/0:27,0:27:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:12,0:12:33:0,33,495 0/1:18,20:38:99:580,0,553 +20 13090728 rs6109712 A T 39487.60 PASS HWP=0.0056;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.176;AN=200;InbreedingCoeff=0.1007;AF=0.066;GQ_STDDEV=110.6;FS=0.0;DP=19040;GQ_MEAN=80.2;POSITIVE_TRAIN_SITE;VQSLOD=6.95;ClippingRankSum=0.263;BaseQRankSum=-0.728;MLEAF=0.067;MLEAC=116;MQ=59.48;QD=15.36;DB;MQRankSum=0.222;CCC=1734;NCC=3 GT:AD:DP:GQ:PL 0/0:28,0:28:66:0,66,990 0/0:20,0:20:60:0,60,719 0/0:11,0:11:30:0,30,450 0/0:25,0:25:63:0,63,945 0/0:21,0:21:63:0,63,796 0/0:24,0:24:66:0,66,990 0/0:23,0:23:63:0,63,945 0/0:22,0:22:62:0,62,927 0/0:26,0:26:63:0,63,945 0/0:11,0:11:30:0,30,450 0/0:25,0:25:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:10,0:10:24:0,24,360 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:16,0:16:9:0,9,135 0/0:31,0:31:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:21,0:21:47:0,47,720 0/1:13,12:25:99:346,0,391 0/0:23,0:23:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:9,0:9:27:0,27,388 0/0:21,0:21:60:0,60,900 0/1:15,19:34:99:527,0,456 0/0:25,0:25:60:0,60,900 0/0:21,0:21:63:0,63,818 0/0:33,0:33:87:0,87,1305 0/0:22,0:22:63:0,63,945 0/0:22,0:22:66:0,66,737 0/0:13,0:13:30:0,30,450 0/0:46,0:46:99:0,120,1800 0/0:38,0:38:99:0,99,1485 0/0:43,0:43:99:0,112,1755 0/0:10,0:10:9:0,9,135 0/0:23,0:23:60:0,60,900 0/0:22,0:22:66:0,66,798 0/0:22,0:22:60:0,60,846 0/0:23,0:23:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:23,0:23:60:0,60,900 0/0:21,0:21:63:0,63,833 0/0:25,0:25:63:0,63,945 0/0:38,0:38:99:0,102,1530 0/0:32,0:32:83:0,83,1326 0/0:38,0:38:99:0,99,1485 0/0:27,0:27:65:0,65,990 0/0:24,0:24:63:0,63,945 0/0:40,0:40:95:0,95,1710 0/0:36,0:36:92:0,92,1440 0/0:25,0:25:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:63:0,63,739 0/0:23,0:23:62:0,62,789 0/0:34,0:34:69:0,69,1395 0/0:24,0:24:63:0,63,945 0/0:26,0:26:69:0,69,1035 0/0:32,0:32:80:0,80,1260 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:35,0:35:93:0,93,1395 0/0:27,0:27:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:10,0:10:30:0,30,361 0/0:31,0:31:62:0,62,1207 0/0:10,0:10:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:24,0:24:69:0,69,1035 0/0:26,0:26:72:0,72,1080 0/0:25,0:25:66:0,66,990 0/0:21,0:21:63:0,63,799 0/0:10,0:10:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:8,0:8:24:0,24,325 0/0:25,0:25:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:21,0:21:63:0,63,747 0/0:4,0:4:9:0,9,135 0/0:19,0:19:48:0,48,720 0/0:22,0:22:60:0,60,900 0/0:16,0:16:25:0,25,515 0/0:23,0:23:62:0,62,945 0/0:11,0:11:27:0,27,405 0/0:21,0:21:60:0,60,900 0/0:24,0:24:69:0,69,1035 0/0:29,0:29:81:0,81,1215 0/0:26,0:26:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:10,0:10:27:0,27,405 0/0:25,0:25:60:0,60,900 0/0:9,0:9:24:0,24,360 0/0:7,0:7:21:0,21,240 0/0:11,0:11:33:0,33,413 0/0:12,0:12:30:0,30,450 0/0:15,0:15:21:0,21,558 +20 13090733 . A AT 87696.50 PASS HWP=0.6857;AC=5;culprit=QD;MQ0=0;ReadPosRankSum=0.121;AN=200;InbreedingCoeff=0.1977;AF=0.047;GQ_STDDEV=147.7;FS=2.367;DP=26524;GQ_MEAN=78.67;VQSLOD=1.72;ClippingRankSum=-0.299;BaseQRankSum=0.033;MLEAF=0.045;MLEAC=78;MQ=60.0;QD=12.63;MQRankSum=0.191;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:35,0:35:0:0,0,984 0/0:34,0:34:33:0,33,1056 0/0:20,0:23:59:0,59,536 0/0:29,0:29:31:0,31,995 0/0:28,3:31:26:0,26,1228 0/0:37,0:37:1:0,1,1123 0/0:30,0:30:49:0,49,1041 0/0:36,0:36:0:0,0,898 0/0:29,0:29:48:0,48,992 0/0:22,0:22:6:0,6,662 0/0:37,0:37:0:0,0,1083 0/0:33,0:33:22:0,22,954 0/0:23,0:23:0:0,0,655 0/0:22,0:22:60:0,60,900 0/0:32,0:32:0:0,0,857 0/0:24,0:24:38:0,38,752 0/1:1,13:23:99:277,0,226 0/0:34,0:39:99:0,102,914 0/0:24,3:27:1:0,1,566 0/0:20,0:38:72:0,72,1265 0/1:11,8:19:99:122,0,932 0/0:31,0:31:25:0,25,924 0/0:26,0:29:77:0,77,688 0/0:9,0:9:27:0,27,388 0/0:24,0:24:29:0,29,873 0/1:15,12:27:99:214,0,865 0/0:30,3:36:27:0,27,780 0/0:42,0:42:14:0,14,1341 0/0:45,7:52:8:0,8,1072 0/0:34,0:34:24:0,24,1016 0/0:32,0:32:61:0,61,1116 0/0:13,0:26:59:0,59,1096 0/0:50,0:55:99:0,150,1401 0/0:62,0:62:0:0,0,1656 0/0:52,4:56:78:0,78,2351 0/1:2,7:18:99:116,0,271 0/0:27,0:27:0:0,0,721 0/0:36,0:36:34:0,34,1116 0/0:28,0:28:0:0,0,780 0/0:46,0:46:0:0,0,1339 0/0:36,0:36:0:0,0,966 0/0:29,0:29:12:0,12,868 0/0:38,0:38:36:0,36,1213 0/0:35,0:35:27:0,27,1147 0/0:39,0:45:99:0,116,1060 0/0:32,0:32:83:0,83,1326 0/0:38,4:42:37:0,37,953 0/0:27,0:27:65:0,65,990 0/0:40,4:44:41:0,41,1861 0/0:40,0:40:95:0,95,1710 0/0:40,0:40:44:0,44,1380 0/0:39,0:39:41:0,41,1328 0/0:26,0:26:0:0,0,750 0/0:27,0:27:0:0,0,624 0/0:43,0:43:99:0,108,1620 0/0:23,0:23:62:0,62,789 0/0:34,0:34:69:0,69,1395 0/0:38,0:38:5:0,5,1200 0/0:42,0:42:32:0,32,1388 0/0:32,0:32:80:0,80,1260 0/0:24,0:24:34:0,34,792 0/1:23,5:28:48:48,0,557 0/0:47,6:60:20:0,20,1239 0/0:33,0:33:25:0,25,1054 0/0:36,0:36:31:0,31,1157 0/0:29,0:29:13:0,13,904 0/0:8,0:8:21:0,21,315 0/0:13,0:13:39:0,39,506 0/0:45,3:55:99:0,114,2662 0/0:15,0:15:9:0,9,457 0/0:30,0:30:52:0,52,990 0/0:36,0:36:33:0,33,1158 0/0:37,0:37:1:0,1,1130 0/0:31,0:31:12:0,12,931 0/0:31,0:31:55:0,55,1024 0/0:14,0:20:48:0,48,938 0/0:27,0:27:43:0,43,900 0/0:15,0:15:6:0,6,472 0/0:30,0:30:0:0,0,855 0/0:32,0:32:0:0,0,913 0/0:25,0:25:34:0,34,864 0/0:8,0:8:0:0,0,225 0/0:23,0:23:29:0,29,756 0/0:28,0:28:4:0,4,923 0/0:27,0:27:0:0,0,756 0/0:36,0:39:99:0,120,1770 0/0:22,0:22:0:0,0,345 0/0:26,0:26:0:0,0,838 0/0:32,0:32:0:0,0,913 0/0:54,4:58:83:0,83,2659 0/0:29,0:29:0:0,0,671 0/0:34,0:34:0:0,0,993 0/0:29,0:29:48:0,48,943 0/0:21,0:21:0:0,0,570 0/0:23,0:28:69:0,69,664 0/0:15,0:15:0:0,0,408 0/0:7,0:7:21:0,21,240 0/0:19,0:22:57:0,57,535 0/0:12,0:12:30:0,30,450 0/0:15,0:15:21:0,21,558 +20 13090733 . AT A 87696.50 PASS HWP=0.6857;AC=10;culprit=QD;MQ0=0;ReadPosRankSum=0.121;AN=200;InbreedingCoeff=0.1977;AF=0.119;GQ_STDDEV=147.7;FS=2.367;DP=26524;GQ_MEAN=78.67;VQSLOD=1.72;ClippingRankSum=-0.299;BaseQRankSum=0.033;MLEAF=0.119;MLEAC=207;MQ=60.0;QD=12.63;MQRankSum=0.191;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:35,0:35:0:0,0,984 0/0:34,0:34:33:0,33,1056 0/1:20,3:23:17:17,0,467 0/0:29,0:29:31:0,31,995 0/0:28,0:31:97:0,97,1309 0/0:37,0:37:1:0,1,1123 0/0:30,0:30:49:0,49,1041 0/0:36,0:36:0:0,0,898 0/0:29,0:29:48:0,48,992 0/0:22,0:22:6:0,6,662 0/0:37,0:37:0:0,0,1083 0/0:33,0:33:22:0,22,954 0/0:23,0:23:0:0,0,655 0/0:22,0:22:60:0,60,900 0/0:32,0:32:0:0,0,857 0/0:24,0:24:38:0,38,752 0/1:1,9:23:99:539,0,681 0/1:34,5:39:25:25,0,796 0/0:24,0:27:72:0,72,646 0/1:20,18:38:99:744,0,1133 0/0:11,0:19:67:0,67,1023 0/0:31,0:31:25:0,25,924 0/0:26,3:29:1:0,1,601 0/0:9,0:9:27:0,27,388 0/0:24,0:24:29:0,29,873 0/0:15,0:27:55:0,55,955 0/0:30,3:36:24:0,24,805 0/0:42,0:42:14:0,14,1341 0/0:45,0:52:99:0,136,1218 0/0:34,0:34:24:0,24,1016 0/0:32,0:32:61:0,61,1116 0/1:13,13:26:99:573,0,983 0/0:50,5:55:40:0,40,1275 0/0:62,0:62:0:0,0,1656 0/0:52,0:56:99:0,173,2459 0/1:2,9:18:99:386,0,439 0/0:27,0:27:0:0,0,721 0/0:36,0:36:34:0,34,1116 0/0:28,0:28:0:0,0,780 0/0:46,0:46:0:0,0,1339 0/0:36,0:36:0:0,0,966 0/0:29,0:29:12:0,12,868 0/0:38,0:38:36:0,36,1213 0/0:35,0:35:27:0,27,1147 0/1:39,6:45:36:36,0,925 0/0:32,0:32:83:0,83,1326 0/0:38,0:42:99:0,115,1044 0/0:27,0:27:65:0,65,990 0/0:40,0:44:99:0,136,1968 0/0:40,0:40:95:0,95,1710 0/0:40,0:40:44:0,44,1380 0/0:39,0:39:41:0,41,1328 0/0:26,0:26:0:0,0,750 0/0:27,0:27:0:0,0,624 0/0:43,0:43:99:0,108,1620 0/0:23,0:23:62:0,62,789 0/0:34,0:34:69:0,69,1395 0/0:38,0:38:5:0,5,1200 0/0:42,0:42:32:0,32,1388 0/0:32,0:32:80:0,80,1260 0/0:24,0:24:34:0,34,792 0/0:23,0:28:70:0,70,642 0/0:47,7:60:24:0,24,1295 0/0:33,0:33:25:0,25,1054 0/0:36,0:36:31:0,31,1157 0/0:29,0:29:13:0,13,904 0/0:8,0:8:21:0,21,315 0/0:13,0:13:39:0,39,506 0/0:45,7:55:11:0,11,2595 0/0:15,0:15:9:0,9,457 0/0:30,0:30:52:0,52,990 0/0:36,0:36:33:0,33,1158 0/0:37,0:37:1:0,1,1130 0/0:31,0:31:12:0,12,931 0/0:31,0:31:55:0,55,1024 0/1:14,6:20:99:265,0,864 0/0:27,0:27:43:0,43,900 0/0:15,0:15:6:0,6,472 0/0:30,0:30:0:0,0,855 0/0:32,0:32:0:0,0,913 0/0:25,0:25:34:0,34,864 0/0:8,0:8:0:0,0,225 0/0:23,0:23:29:0,29,756 0/0:28,0:28:4:0,4,923 0/0:27,0:27:0:0,0,756 0/0:36,3:39:44:0,44,1683 0/0:22,0:22:0:0,0,345 0/0:26,0:26:0:0,0,838 0/0:32,0:32:0:0,0,913 0/0:54,0:58:99:0,178,2767 0/0:29,0:29:0:0,0,671 0/0:34,0:34:0:0,0,993 0/0:29,0:29:48:0,48,943 0/0:21,0:21:0:0,0,570 0/1:23,5:28:41:41,0,579 0/0:15,0:15:0:0,0,408 0/0:7,0:7:21:0,21,240 0/1:19,3:22:19:19,0,468 0/0:12,0:12:30:0,30,450 0/0:15,0:15:21:0,21,558 +20 13090745 rs2236126 G C 403486.00 PASS HWP=0.0;AC=79;culprit=MQ;MQ0=0;ReadPosRankSum=0.227;AN=200;InbreedingCoeff=0.1493;AF=0.39;GQ_STDDEV=259.72;FS=0.0;DP=27646;GQ_MEAN=234.06;POSITIVE_TRAIN_SITE;VQSLOD=6.21;ClippingRankSum=-0.352;BaseQRankSum=-1.098;MLEAF=0.391;MLEAC=680;MQ=60.0;QD=22.36;DB;MQRankSum=0.048;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/1:11,27:38:99:896,0,305 0/1:15,20:35:99:569,0,486 1/1:0,32:32:96:1119,96,0 0/1:19,19:38:99:542,0,626 0/1:17,26:43:99:763,0,456 0/0:31,0:31:63:0,63,945 0/1:17,21:38:99:623,0,545 0/1:20,17:37:99:554,0,618 1/1:3,29:32:12:990,12,0 0/1:12,15:27:99:445,0,366 0/1:17,19:36:99:607,0,555 0/0:25,0:25:60:0,60,900 0/0:24,0:24:69:0,69,1028 0/0:22,0:22:60:0,60,900 0/1:14,23:37:99:667,0,384 0/0:24,0:24:63:0,63,895 0/1:18,16:34:99:539,0,1028 0/0:21,0:21:60:0,60,900 0/0:28,0:28:66:0,66,990 0/1:24,19:43:99:744,0,1133 0/1:12,21:33:99:638,0,549 1/1:0,32:32:96:1082,96,0 0/0:23,0:23:63:0,63,945 0/0:21,0:21:60:0,60,863 0/0:28,0:28:72:0,72,1080 0/1:16,18:34:99:497,0,803 0/0:28,0:28:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:26,0:26:72:0,72,1080 0/1:32,13:45:99:340,0,1000 1/1:2,32:34:57:1072,57,0 0/1:19,18:37:99:573,0,983 1/1:0,66:66:99:2517,199,0 0/1:44,32:76:99:904,0,1667 0/1:27,48:75:99:1570,0,810 0/1:10,11:21:99:386,0,609 0/1:10,18:28:99:545,0,291 1/1:0,36:36:99:1210,108,0 1/1:0,37:37:99:1295,110,0 0/0:27,0:27:62:0,62,1035 0/0:26,0:26:63:0,63,945 1/1:0,26:26:78:908,78,0 0/1:17,22:39:99:635,0,507 0/1:11,25:36:99:795,0,307 0/0:35,0:35:69:0,69,1260 1/1:0,44:44:99:1684,132,0 0/0:34,0:34:86:0,86,1155 0/0:27,0:27:65:0,65,990 0/1:29,23:52:99:750,0,1090 0/1:44,35:79:99:985,0,1354 0/0:26,0:26:60:0,60,900 0/1:15,15:30:99:467,0,490 0/0:25,0:25:60:0,60,900 0/1:17,10:27:99:322,0,632 0/0:27,0:27:60:0,60,900 0/1:14,25:39:99:792,0,438 0/0:30,0:30:75:0,75,1125 0/0:38,0:38:96:0,96,1440 0/1:20,20:40:99:582,0,693 0/1:18,29:47:99:1045,0,570 0/1:10,17:27:99:452,0,273 0/0:22,0:22:60:0,60,900 0/0:49,0:49:99:0,108,1620 0/1:20,14:34:99:358,0,728 0/0:22,0:22:60:0,60,900 1/1:0,31:31:93:1094,93,0 1/1:0,17:17:51:614,51,0 0/0:16,0:16:10:0,10,631 0/1:41,36:77:99:1228,0,1491 0/0:22,0:22:51:0,51,778 0/1:9,21:30:99:660,0,253 0/1:17,14:31:99:429,0,549 0/1:22,16:38:99:445,0,732 0/1:13,16:29:99:504,0,446 0/0:29,0:29:60:0,60,900 0/1:16,8:24:99:265,0,864 0/1:14,21:35:99:656,0,464 0/1:10,10:20:99:314,0,304 0/0:26,0:26:60:0,60,900 0/1:8,25:33:99:737,0,243 0/0:25,0:25:63:0,63,895 0/0:9,0:9:27:0,27,311 0/1:11,13:24:99:445,0,314 0/1:13,20:33:99:649,0,458 0/1:11,14:25:99:472,0,337 0/1:19,33:52:99:970,0,626 0/1:16,7:23:99:212,0,570 1/1:0,30:30:90:1090,90,0 0/0:24,0:24:60:0,60,900 0/1:35,37:72:99:1079,0,1353 0/1:13,16:29:99:496,0,417 0/1:18,15:33:99:453,0,558 0/1:17,13:30:99:422,0,553 0/1:12,14:26:99:508,0,446 1/1:1,41:42:88:1490,88,0 0/0:15,0:15:42:0,42,583 0/1:5,11:16:99:376,0,177 1/1:0,29:29:87:1141,87,0 0/1:10,4:14:99:114,0,362 0/0:21,0:21:60:0,60,900 +20 13098135 rs150175260 T C 4903.69 PASS HWP=1.0;AC=2;culprit=ReadPosRankSum;MQ0=0;ReadPosRankSum=2.68;AN=200;InbreedingCoeff=-0.0017;AF=0.001724;GQ_STDDEV=101.09;FS=0.463;DP=29532;GQ_MEAN=78.68;POSITIVE_TRAIN_SITE;VQSLOD=3.54;ClippingRankSum=-0.71;BaseQRankSum=4.6;MLEAF=0.001724;MLEAC=3;MQ=59.68;QD=14.42;DB;MQRankSum=0.307;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:25,0:25:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:30,0:30:66:0,66,990 0/0:43,0:43:87:0,87,1305 0/0:26,0:26:66:0,66,990 0/0:31,0:31:75:0,75,1125 0/0:34,0:34:81:0,81,1215 0/0:26,0:26:69:0,69,1035 0/0:30,0:30:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:41,0:41:87:0,87,1305 0/0:42,0:42:75:0,75,1125 0/0:30,0:30:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:31,0:31:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:35,0:35:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:30,0:30:69:0,69,1035 0/0:32,0:32:66:0,66,990 0/0:30,0:30:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:32,0:32:66:0,66,1167 0/0:37,0:37:93:0,93,1395 0/0:35,0:35:72:0,72,1080 0/0:30,0:30:66:0,66,990 0/0:29,0:29:69:0,69,1035 0/0:45,0:45:90:0,90,1350 0/0:46,0:46:99:0,101,1530 0/0:70,0:70:99:0,120,1800 0/0:29,0:29:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:26,0:26:66:0,66,990 0/0:55,0:55:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:28,0:28:75:0,75,1101 0/0:31,0:31:72:0,72,1080 0/0:52,0:52:99:0,120,1800 0/1:92,84:176:99:2521,0,2707 0/0:34,0:34:84:0,84,1260 0/0:43,0:43:97:0,97,1485 0/0:46,0:46:99:0,102,1530 0/0:46,0:46:99:0,102,1530 0/0:36,0:36:93:0,93,1395 0/1:58,55:113:99:1662,0,1606 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:30,0:30:70:0,70,1170 0/0:34,0:34:65:0,65,1116 0/0:57,0:57:99:0,120,1800 0/0:48,0:48:74:0,74,1800 0/0:45,0:45:96:0,96,1440 0/0:50,0:50:99:0,114,1710 0/0:32,0:32:72:0,72,1080 0/0:31,0:31:69:0,69,1035 0/0:43,0:43:90:0,90,1350 0/0:28,0:28:66:0,66,990 0/0:29,0:29:63:0,63,945 0/0:30,0:30:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:49,0:49:99:0,103,1620 0/0:25,0:25:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:31,0:31:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:53,0:53:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:33,0:33:66:0,66,990 +20 13134768 rs6078938 T C 264563.00 PASS HWP=0.0593;AC=40;culprit=FS;MQ0=0;ReadPosRankSum=0.214;AN=200;InbreedingCoeff=0.0701;AF=0.135;GQ_STDDEV=417.62;FS=0.528;DP=42732;GQ_MEAN=273.78;POSITIVE_TRAIN_SITE;VQSLOD=5.93;ClippingRankSum=-0.218;BaseQRankSum=3.58;MLEAF=0.135;MLEAC=235;MQ=59.68;QD=17.23;DB;MQRankSum=0.275;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:27,24:51:99:740,0,703 0/1:31,27:58:99:772,0,862 1/1:1,61:62:99:2132,183,0 0/0:30,0:30:75:0,75,1036 0/0:47,0:47:99:0,108,1620 0/0:39,0:39:90:0,90,1350 0/1:36,45:81:99:1491,0,1012 0/1:28,22:50:99:633,0,708 1/1:4,64:68:99:2445,113,0 0/0:41,0:41:99:0,108,1620 0/0:28,0:28:72:0,72,1080 0/0:28,0:28:69:0,69,1035 0/0:36,0:36:87:0,87,1305 0/0:48,0:48:99:0,102,1530 0/0:42,0:42:96:0,96,1440 0/0:55,0:55:99:0,119,1744 0/0:46,0:46:99:0,108,1620 0/0:56,0:56:99:0,120,1800 0/0:38,0:38:92:0,92,1395 0/0:65,0:65:99:0,120,1800 0/0:43,0:43:99:0,114,1710 0/0:40,0:40:99:0,99,1485 0/0:42,0:42:90:0,90,1350 0/0:67,0:67:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:47,0:47:99:0,111,1665 0/0:35,0:35:75:0,75,1125 0/1:35,36:71:99:1222,0,915 1/1:0,50:50:99:1943,150,0 0/0:28,0:28:63:0,63,945 0/0:76,0:76:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:29,0:29:74:0,74,1125 0/0:31,0:31:72:0,72,1063 1/1:0,70:70:99:2458,210,0 0/0:53,0:53:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:37,0:37:93:0,93,1395 0/1:31,25:56:99:780,0,918 0/0:57,0:57:99:0,120,1800 0/1:39,45:84:99:1390,0,1121 0/0:68,0:68:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/1:65,51:116:99:1646,0,1850 0/0:60,0:60:99:0,120,1800 0/0:58,0:58:99:0,120,1800 1/1:0,56:56:99:1996,167,0 0/0:40,0:40:86:0,86,1305 0/1:30,35:65:99:1123,0,791 0/0:65,0:65:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:42,0:42:94:0,94,1665 0/0:53,0:53:99:0,120,1800 0/1:68,63:131:99:2063,0,1924 0/0:41,0:41:93:0,93,1395 0/1:33,36:69:99:1165,0,896 0/1:31,45:76:99:1389,0,807 0/0:33,0:33:64:0,64,1125 0/0:31,0:31:60:0,60,900 0/0:79,0:79:99:0,120,1800 0/0:25,0:25:60:0,60,900 1/1:5,85:90:99:3296,234,0 1/1:0,53:53:99:2100,159,0 0/0:69,0:69:99:0,120,1800 0/1:26,29:55:99:923,0,676 0/0:57,0:57:99:0,120,1800 0/0:36,0:36:84:0,84,1260 0/0:43,0:43:96:0,96,1440 0/1:44,19:63:99:590,0,1208 0/0:48,0:48:99:0,111,1665 0/0:37,0:37:87:0,87,1305 0/0:31,0:31:78:0,78,1170 0/0:33,0:33:82:0,82,1260 0/0:29,0:29:69:0,69,1035 0/0:36,0:36:87:0,87,1305 0/1:31,46:77:99:1493,0,800 0/1:51,52:103:99:1687,0,1459 0/0:37,0:37:87:0,87,1305 1/1:2,69:71:99:2363,164,0 0/0:43,0:43:87:0,87,1305 0/1:67,53:120:99:1738,0,1973 0/1:33,43:76:99:1300,0,827 0/1:22,29:51:99:888,0,534 0/0:41,0:41:99:0,102,1530 0/1:19,25:44:99:843,0,510 0/1:28,35:63:99:1070,0,646 0/0:25,0:25:60:0,60,900 0/1:31,25:56:99:758,0,808 1/1:0,48:48:99:1821,143,0 0/0:27,0:27:63:0,63,945 0/0:31,0:31:78:0,78,1170 +20 13140617 . C CT 20005.50 PASS HWP=0.0013;AC=7;culprit=QD;MQ0=0;ReadPosRankSum=0.053;AN=200;InbreedingCoeff=0.0447;AF=0.039;GQ_STDDEV=101.07;FS=0.0;DP=66477;GQ_MEAN=56.07;VQSLOD=2.42;ClippingRankSum=-0.401;BaseQRankSum=-0.08;MLEAF=0.033;MLEAC=58;MQ=59.66;QD=1.86;MQRankSum=0.233;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:48,5:53:53:0,53,1173 0/0:51,6:57:37:0,37,1227 0/0:62,0:62:0:0,0,1945 0/0:72,0:79:99:0,214,1957 0/0:57,0:63:99:0,170,1589 0/0:57,8:68:18:0,18,1390 0/0:71,0:71:59:0,59,2315 0/0:38,0:38:78:0,78,1170 0/0:43,0:43:97:0,97,1575 0/0:61,7:72:40:0,40,1533 0/0:56,0:66:99:0,168,1564 0/0:44,0:48:99:0,131,1180 0/0:76,0:85:99:0,227,2056 0/0:53,0:56:99:0,158,1448 0/0:59,0:68:99:0,174,1547 0/0:171,0:171:0:0,0,4534 0/0:109,14:140:70:0,70,2883 0/0:169,0:169:0:0,0,4773 0/0:139,0:139:0:0,0,3797 0/0:143,14:175:99:0,172,3755 0/0:154,0:154:0:0,0,3821 0/0:172,0:172:0:0,0,5150 0/0:172,0:172:0:0,0,5059 0/0:106,0:106:50:0,50,3196 0/0:46,0:84:99:0,137,1308 0/0:97,0:97:52:0,52,2883 0/0:72,0:72:0:0,0,2056 0/0:32,0:72:72:0,72,851 0/0:80,0:89:99:0,240,2204 0/0:59,9:73:83:0,83,1567 0/1:64,10:80:12:12,0,1608 0/1:28,5:39:30:30,0,663 0/0:118,0:118:22:0,22,3810 0/0:93,9:116:99:0,104,2468 0/0:118,0:118:0:0,0,3662 0/0:32,0:36:94:0,94,804 0/1:35,5:40:12:12,0,837 0/1:106,20:136:95:95,0,2579 0/0:50,0:59:99:0,149,1351 0/0:65,0:65:90:0,90,1800 0/0:38,0:38:76:0,76,1170 0/0:64,0:64:60:0,60,1800 0/0:31,0:31:62:0,62,1162 0/0:87,0:87:26:0,26,2640 0/0:83,0:83:0:0,0,2462 0/0:99,0:99:32:0,32,2919 0/1:48,7:61:35:35,0,1205 0/0:71,0:79:99:0,211,1890 0/0:123,0:123:0:0,0,3964 0/0:70,0:70:65:0,65,1800 0/0:70,0:70:12:0,12,2183 0/0:43,0:50:99:0,131,1240 0/0:79,0:79:46:0,46,2315 0/0:58,0:58:70:0,70,1800 0/0:76,0:85:99:0,227,2087 0/0:92,0:92:0:0,0,2613 0/0:77,0:85:99:0,231,2137 0/0:69,5:82:99:0,128,1916 0/0:107,0:107:0:0,0,3199 0/0:69,0:69:74:0,74,1800 0/0:38,0:38:78:0,78,1181 0/0:72,0:72:19:0,19,2104 0/0:103,0:113:99:0,309,2883 0/0:53,0:53:90:0,90,1800 0/0:51,4:55:59:0,59,1302 0/0:176,0:176:0:0,0,4803 0/0:36,0:36:0:0,0,1129 0/0:39,0:39:34:0,34,1253 0/0:86,9:100:56:0,56,2176 0/0:38,0:49:99:0,113,1013 0/0:79,0:79:99:0,120,1800 0/0:85,0:85:46:0,46,2875 0/0:108,0:108:0:0,0,3465 0/0:57,0:63:99:0,170,1552 0/0:57,0:64:99:0,172,1602 0/0:50,0:50:0:0,0,1493 0/0:41,0:47:99:0,122,1117 0/0:67,0:67:30:0,30,2277 0/0:44,0:50:99:0,132,1214 0/0:44,0:44:69:0,69,1395 0/0:46,0:46:59:0,59,1683 0/0:47,0:50:99:0,140,1280 0/0:31,0:36:94:0,94,866 0/0:88,0:88:25:0,25,2793 0/0:54,0:54:33:0,33,1792 0/0:103,0:103:16:0,16,3361 0/0:35,0:38:99:0,104,907 0/0:7,0:7:21:0,21,268 0/0:121,8:143:99:0,230,3316 0/0:105,0:105:99:0,120,1800 0/1:23,7:30:96:96,0,527 0/0:31,0:31:0:0,0,953 0/0:39,0:39:64:0,64,1055 0/0:40,0:40:7:0,7,1300 0/0:55,0:55:0:0,0,1580 0/1:23,4:27:21:21,0,548 0/0:32,0:37:95:0,95,849 0/0:56,0:56:17:0,17,1837 0/0:32,0:36:96:0,96,844 0/0:49,0:49:22:0,22,1613 +20 13140617 . CT C 20005.50 PASS HWP=0.0013;AC=16;culprit=QD;MQ0=0;ReadPosRankSum=0.053;AN=200;InbreedingCoeff=0.0447;AF=0.063;GQ_STDDEV=101.07;FS=0.0;DP=66477;GQ_MEAN=56.07;VQSLOD=2.42;ClippingRankSum=-0.401;BaseQRankSum=-0.08;MLEAF=0.053;MLEAC=93;MQ=59.66;QD=1.86;MQRankSum=0.233;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:48,0:53:99:0,144,1276 0/0:51,0:57:99:0,156,1361 0/0:62,0:62:0:0,0,1945 0/0:72,7:79:99:0,120,1846 0/0:57,6:63:42:0,42,1443 0/0:57,3:68:99:0,146,1657 0/0:71,0:71:59:0,59,2315 0/0:38,0:38:78:0,78,1170 0/0:43,0:43:97:0,97,1575 0/0:61,4:72:99:0,152,1772 0/0:56,10:66:23:0,23,1396 0/0:44,4:48:54:0,54,1092 0/0:76,9:85:33:0,33,1835 0/0:53,3:56:99:0,106,1388 0/1:59,9:68:55:55,0,1344 0/0:171,0:171:0:0,0,4534 0/1:109,17:140:51:51,0,2895 0/0:169,0:169:0:0,0,4773 0/0:139,0:139:0:0,0,3797 0/0:143,18:175:74:0,74,3770 0/0:154,0:154:0:0,0,3821 0/0:172,0:172:0:0,0,5150 0/0:172,0:172:0:0,0,5059 0/0:106,0:106:50:0,50,3196 0/1:46,38:84:99:776,0,1055 0/0:97,0:97:52:0,52,2883 0/0:72,0:72:0:0,0,2056 0/1:32,37:72:99:776,0,672 0/0:80,9:89:11:0,11,1945 0/1:59,5:73:23:23,0,1637 0/0:64,6:80:83:0,83,1882 0/0:28,6:39:7:0,7,735 0/0:118,0:118:22:0,22,3810 0/1:93,14:116:38:38,0,2381 0/0:118,0:118:0:0,0,3662 0/1:32,4:36:8:8,0,696 0/0:35,0:40:99:0,107,959 0/0:106,10:136:99:0,141,3101 0/1:50,9:59:69:69,0,1173 0/0:65,0:65:90:0,90,1800 0/0:38,0:38:76:0,76,1170 0/0:64,0:64:60:0,60,1800 0/0:31,0:31:62:0,62,1162 0/0:87,0:87:26:0,26,2640 0/0:83,0:83:0:0,0,2462 0/0:99,0:99:32:0,32,2919 0/0:48,6:61:0:0,0,1248 0/0:71,8:79:25:0,25,1679 0/0:123,0:123:0:0,0,3964 0/0:70,0:70:65:0,65,1800 0/0:70,0:70:12:0,12,2183 0/1:43,7:50:7:7,0,1087 0/0:79,0:79:46:0,46,2315 0/0:58,0:58:70:0,70,1800 0/0:76,9:85:7:0,7,1837 0/0:92,0:92:0:0,0,2613 0/0:77,8:85:27:0,27,1907 0/0:69,8:82:58:0,58,1857 0/0:107,0:107:0:0,0,3199 0/0:69,0:69:74:0,74,1800 0/0:38,0:38:78:0,78,1181 0/0:72,0:72:19:0,19,2104 0/0:103,10:113:70:0,70,2611 0/0:53,0:53:90:0,90,1800 0/0:51,0:55:99:0,154,1410 0/0:176,0:176:0:0,0,4803 0/0:36,0:36:0:0,0,1129 0/0:39,0:39:34:0,34,1253 0/0:86,5:100:99:0,204,2474 0/1:38,11:49:99:155,0,865 0/0:79,0:79:99:0,120,1800 0/0:85,0:85:46:0,46,2875 0/0:108,0:108:0:0,0,3465 0/0:57,6:63:28:0,28,1390 0/1:57,7:64:6:6,0,1409 0/0:50,0:50:0:0,0,1493 0/1:41,6:47:30:30,0,975 0/0:67,0:67:30:0,30,2277 0/1:44,6:50:20:20,0,1063 0/0:44,0:44:69:0,69,1395 0/0:46,0:46:59:0,59,1683 0/0:47,3:50:64:0,64,1194 0/1:31,5:36:33:33,0,756 0/0:88,0:88:25:0,25,2793 0/0:54,0:54:33:0,33,1792 0/0:103,0:103:16:0,16,3361 0/0:35,3:38:26:0,26,819 0/0:7,0:7:21:0,21,268 0/0:121,14:143:63:0,63,3250 0/0:105,0:105:99:0,120,1800 0/0:23,0:30:70:0,70,618 0/0:31,0:31:0:0,0,953 0/0:39,0:39:64:0,64,1055 0/0:40,0:40:7:0,7,1300 0/0:55,0:55:0:0,0,1580 0/0:23,0:27:70:0,70,630 0/1:32,5:37:32:32,0,738 0/0:56,0:56:17:0,17,1837 0/1:32,4:36:6:6,0,736 0/0:49,0:49:22:0,22,1613 +20 13140720 rs61738161 G A 50626.10 PASS HWP=0.0;AC=6;culprit=QD;MQ0=0;ReadPosRankSum=0.841;AN=200;InbreedingCoeff=0.2756;AF=0.024;GQ_STDDEV=202.18;FS=2.874;DP=39263;GQ_MEAN=121.03;POSITIVE_TRAIN_SITE;VQSLOD=2.7;ClippingRankSum=-0.402;BaseQRankSum=-3.201;MLEAF=0.024;MLEAC=41;MQ=59.5;QD=17.21;DB;MQRankSum=0.02;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:42,0:42:96:0,96,1440 0/0:41,0:41:99:0,99,1485 0/0:38,0:38:80:0,80,1260 0/0:36,0:36:90:0,90,1350 0/0:40,0:40:90:0,90,1350 0/0:30,0:30:72:0,72,1080 0/0:51,0:51:74:0,74,1755 0/0:38,0:38:78:0,78,1170 0/0:43,0:43:97:0,97,1575 0/0:42,0:42:99:0,99,1665 0/0:35,0:35:78:0,78,1170 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:69:0,69,1035 0/0:39,0:39:67:0,67,1125 0/0:57,0:57:99:0,120,1800 0/0:42,0:42:84:0,84,1260 0/0:35,0:35:87:0,87,1305 0/0:42,0:42:99:0,99,1485 0/0:42,0:42:99:0,105,1562 0/0:61,0:61:99:0,116,1800 0/0:44,0:44:93:0,93,1395 0/0:50,0:50:99:0,100,1755 0/0:44,0:44:99:0,99,1665 0/0:53,0:53:76:0,76,1530 0/0:63,0:63:99:0,120,1800 0/0:50,0:50:72:0,72,1463 0/0:45,0:45:99:0,108,1620 0/0:49,0:49:92:0,92,1710 0/0:44,0:44:99:0,108,1620 0/0:37,0:37:81:0,81,1215 0/0:30,0:30:66:0,66,1170 0/0:53,0:53:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:34,0:34:63:0,63,945 0/0:41,0:41:90:0,90,1350 0/1:77,79:156:99:2374,0,2368 0/0:43,0:43:66:0,66,1575 0/0:65,0:65:90:0,90,1800 0/0:38,0:38:76:0,76,1170 0/0:41,0:41:84:0,84,1395 0/0:31,0:31:62:0,62,1162 0/0:55,0:55:99:0,120,1800 0/0:50,0:50:63:0,63,1665 0/0:59,0:59:70:0,70,1800 0/0:62,0:62:99:0,112,1800 0/0:60,0:60:99:0,120,1800 0/0:58,0:58:63:0,63,1800 0/0:70,0:70:65:0,65,1800 0/0:51,0:51:99:0,114,1710 0/0:42,0:42:69:0,69,1305 0/0:45,0:45:99:0,114,1710 0/0:36,0:36:84:0,84,1260 0/0:42,0:42:99:0,102,1530 0/0:51,0:51:99:0,120,1800 0/0:61,0:61:99:0,105,1800 0/0:63,0:63:99:0,105,1575 0/0:71,0:71:99:0,120,1800 0/0:69,0:69:74:0,74,1800 0/0:38,0:38:78:0,78,1181 0/0:37,0:37:78:0,78,1170 0/0:88,0:88:83:0,83,1800 0/0:53,0:53:90:0,90,1800 0/0:38,0:38:78:0,78,1260 0/0:57,0:57:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:65,0:65:99:0,120,1800 0/0:26,0:26:65:0,65,1035 1/1:5,91:96:99:3154,231,0 0/1:36,33:69:99:915,0,1163 0/0:54,0:54:96:0,96,1800 0/1:32,33:65:99:988,0,1091 0/0:34,0:34:87:0,87,1305 0/0:30,0:30:63:0,63,945 0/0:31,0:31:69:0,69,1035 0/0:40,0:40:99:0,99,1485 0/0:30,0:30:69:0,69,1035 0/0:44,0:44:69:0,69,1395 0/0:25,0:25:61:0,61,945 0/0:26,0:26:60:0,60,900 0/0:26,0:26:63:0,63,990 0/0:38,0:38:93:0,93,1395 0/0:29,0:29:63:0,63,945 0/0:54,0:54:99:0,120,1800 0/0:35,0:35:75:0,75,1125 0/0:34,0:34:99:0,99,1424 0/0:54,0:54:99:0,120,1800 0/1:56,60:116:99:1609,0,2002 0/0:35,0:35:63:0,63,1116 0/0:41,0:41:96:0,96,1440 0/0:39,0:39:99:0,102,1530 0/0:32,0:32:75:0,75,1125 0/0:47,0:47:62:0,62,1530 0/0:28,0:28:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:43,0:43:93:0,93,1395 0/0:29,0:29:75:0,75,1125 0/0:37,0:37:78:0,78,1305 +20 13251316 rs77255807 T C 8515.59 PASS HWP=1.0;AC=3;culprit=MQ;MQ0=0;ReadPosRankSum=0.466;AN=200;InbreedingCoeff=-0.0087;AF=0.008621;GQ_STDDEV=60.34;FS=1.741;DP=20438;GQ_MEAN=68.67;POSITIVE_TRAIN_SITE;VQSLOD=4.76;ClippingRankSum=-0.159;BaseQRankSum=2.58;MLEAF=0.008621;MLEAC=15;MQ=60.0;QD=13.69;DB;MQRankSum=0.533;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,787 0/0:27,0:27:62:0,62,983 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,790 0/0:26,0:26:63:0,63,945 0/0:21,0:21:60:0,60,754 0/0:24,0:24:60:0,60,888 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,876 0/0:20,0:20:60:0,60,727 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,771 0/0:29,0:29:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:31,0:31:60:0,60,1035 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,755 0/0:22,0:22:60:0,60,784 0/0:30,0:30:72:0,72,1080 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,796 0/0:29,0:29:63:0,63,1170 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,718 0/0:28,0:28:60:0,60,900 0/0:20,0:20:60:0,60,611 0/0:22,0:22:60:0,60,900 0/0:30,0:30:67:0,67,966 0/0:21,0:21:63:0,63,745 0/0:26,0:26:60:0,60,900 0/0:22,0:22:60:0,60,811 0/0:28,0:28:60:0,60,900 0/0:20,0:20:60:0,60,727 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,890 0/0:21,0:21:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,797 0/0:20,0:20:60:0,60,762 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,883 0/0:29,0:29:60:0,60,900 0/0:20,0:20:60:0,60,724 0/0:25,0:25:67:0,67,844 0/1:27,22:49:99:672,0,710 0/0:22,0:22:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,856 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,851 0/0:23,0:23:60:0,60,900 0/0:19,0:19:45:0,45,648 0/0:20,0:20:60:0,60,745 0/0:20,0:20:60:0,60,723 0/0:21,0:21:60:0,60,737 0/0:20,0:20:60:0,60,746 0/0:25,0:25:60:0,60,797 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/1:20,9:29:99:264,0,631 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,819 0/0:23,0:23:63:0,63,945 0/1:24,21:45:99:669,0,608 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,712 0/0:20,0:20:60:0,60,687 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,881 0/0:20,0:20:60:0,60,734 0/0:21,0:21:60:0,60,809 0/0:23,0:23:51:0,51,765 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,882 0/0:26,0:26:60:0,60,900 0/0:22,0:22:54:0,54,810 0/0:24,0:24:60:0,60,900 +20 13260252 rs911642 C T 165233.00 PASS HWP=0.0;AC=59;culprit=MQ;MQ0=0;ReadPosRankSum=0.212;AN=200;InbreedingCoeff=0.1405;AF=0.422;GQ_STDDEV=96.65;FS=1.528;DP=12381;GQ_MEAN=89.72;POSITIVE_TRAIN_SITE;VQSLOD=4.96;ClippingRankSum=-0.049;BaseQRankSum=-1.468;MLEAF=0.433;MLEAC=750;MQ=60.0;QD=20.36;DB;MQRankSum=0.177;CCC=1734;NCC=3 GT:AD:DP:GQ:PL 0/0:13,0:13:28:0,28,495 0/0:12,0:12:24:0,24,360 0/0:14,0:14:36:0,36,540 0/0:8,0:8:21:0,21,315 0/1:6,10:16:99:301,0,191 0/0:11,0:11:0:0,0,267 0/0:7,0:7:21:0,21,263 0/0:13,0:13:36:0,36,482 0/0:12,0:12:33:0,33,457 0/0:10,0:10:27:0,27,405 0/1:4,3:7:96:96,0,145 0/1:6,5:11:99:157,0,215 0/1:11,7:18:99:215,0,360 0/0:12,0:12:27:0,27,405 1/1:0,11:11:33:404,33,0 0/1:11,3:14:71:71,0,336 0/0:8,0:8:21:0,21,313 0/0:8,0:8:21:0,21,270 0/1:5,11:16:99:368,0,151 0/1:6,8:14:99:222,0,196 0/1:4,7:11:95:233,0,95 0/1:9,9:18:99:265,0,288 0/0:8,0:8:21:0,21,298 0/1:9,16:25:99:519,0,298 0/1:8,9:17:99:289,0,253 0/1:5,6:11:99:185,0,130 0/1:12,4:16:97:97,0,368 0/1:9,9:18:99:231,0,265 0/0:14,0:14:37:0,37,496 0/0:13,0:13:36:0,36,466 0/0:14,0:14:42:0,42,483 0/1:13,9:22:99:244,0,428 0/1:10,7:17:99:192,0,309 0/0:13,0:13:30:0,30,450 0/1:10,6:16:99:157,0,324 0/0:9,0:9:27:0,27,347 1/1:0,17:17:51:537,51,0 1/1:0,21:21:63:748,63,0 0/0:7,0:7:21:0,21,251 0/1:7,4:11:99:107,0,188 0/0:11,0:11:0:0,0,312 0/0:13,0:13:33:0,33,459 0/1:7,6:13:99:176,0,213 0/0:14,0:14:24:0,24,447 0/0:7,0:7:21:0,21,266 0/1:11,5:16:99:127,0,330 0/0:12,0:12:30:0,30,421 0/0:25,0:25:60:0,60,900 0/1:13,3:16:59:59,0,487 0/0:14,0:14:35:0,35,531 0/0:14,0:14:39:0,39,585 0/0:11,0:11:24:0,24,360 0/0:14,0:14:39:0,39,471 0/1:4,5:9:99:151,0,123 0/1:3,7:10:89:186,0,89 1/1:0,16:16:48:537,48,0 0/0:15,0:15:39:0,39,540 0/0:15,0:15:27:0,27,500 0/1:4,9:13:99:260,0,104 0/1:8,7:15:99:206,0,248 0/0:7,0:7:21:0,21,251 0/1:5,9:14:99:275,0,137 0/0:13,0:13:27:0,27,405 0/1:5,7:12:99:202,0,140 0/1:7,9:16:99:231,0,226 0/1:4,5:9:99:168,0,128 0/0:2,0:2:6:0,6,75 0/0:6,0:6:0:0,0,12 0/1:6,6:12:99:180,0,199 0/1:3,3:6:91:91,0,99 0/1:1,8:9:11:207,0,11 1/1:0,10:10:30:319,30,0 0/1:8,10:18:99:227,0,230 0/0:2,0:2:6:0,6,68 0/0:5,0:5:0:0,0,33 1/1:0,3:3:9:101,9,0 0/0:4,0:4:0:0,0,11 0/0:4,0:4:0:0,0,85 0/1:3,2:5:52:52,0,105 0/0:2,0:2:6:0,6,76 0/1:1,3:4:29:88,0,29 0/0:7,0:7:21:0,21,259 0/0:7,0:7:18:0,18,270 0/1:6,3:9:54:54,0,160 0/0:10,0:10:30:0,30,328 0/0:7,0:7:21:0,21,263 0/1:10,13:23:99:362,0,287 0/1:7,10:17:99:308,0,245 0/0:22,0:22:60:0,60,795 0/1:11,4:15:94:94,0,387 0/0:12,0:12:33:0,33,495 0/1:8,9:17:99:270,0,238 0/0:6,0:6:0:0,0,173 0/0:7,0:7:21:0,21,268 0/1:12,9:21:99:197,0,337 0/1:5,7:12:99:227,0,106 0/0:4,0:4:0:0,0,49 0/1:7,7:14:99:189,0,198 1/1:0,7:7:21:253,21,0 1/1:0,6:6:18:188,18,0 +20 13260480 rs3747933 C G 21614.70 PASS HWP=1.0;AC=8;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.095;AN=200;InbreedingCoeff=-0.0152;AF=0.015;GQ_STDDEV=137.59;FS=0.596;DP=21483;GQ_MEAN=82.7;POSITIVE_TRAIN_SITE;VQSLOD=4.37;ClippingRankSum=0.178;BaseQRankSum=-0.894;MLEAF=0.015;MLEAC=26;MQ=59.47;QD=14.14;DB;MQRankSum=0.018;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/1:32,40:72:99:1220,0,972 0/0:25,0:25:62:0,62,875 0/0:21,0:21:60:0,60,790 0/0:24,0:24:60:0,60,884 0/0:20,0:20:60:0,60,711 0/0:28,0:28:63:0,63,990 0/1:27,34:61:99:1001,0,845 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,866 0/0:24,0:24:60:0,60,900 0/0:23,0:23:63:0,63,894 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,801 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,825 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,893 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,775 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/1:39,40:79:99:1277,0,1346 0/0:20,0:20:60:0,60,689 0/0:23,0:23:60:0,60,864 0/0:24,0:24:63:0,63,836 0/0:20,0:20:60:0,60,761 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,683 0/0:20,0:20:60:0,60,617 0/0:23,0:23:60:0,60,900 0/0:25,0:25:64:0,64,934 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,877 0/0:27,0:27:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,869 0/0:26,0:26:62:0,62,1035 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,710 0/0:20,0:20:60:0,60,701 0/0:27,0:27:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:21,0:21:60:0,60,778 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:21,0:21:60:0,60,801 0/0:25,0:25:60:0,60,865 0/0:27,0:27:66:0,66,990 0/0:24,0:24:63:0,63,842 0/0:23,0:23:60:0,60,779 0/0:32,0:32:69:0,69,1035 0/0:21,0:21:60:0,60,879 0/1:14,17:31:99:597,0,442 0/0:28,0:28:63:0,63,945 0/0:23,0:23:60:0,60,792 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:16,17:33:99:595,0,554 0/0:22,0:22:60:0,60,865 0/0:23,0:23:60:0,60,900 0/0:30,0:30:60:0,60,900 0/1:22,27:49:99:826,0,723 0/1:36,26:62:99:829,0,1205 0/0:23,0:23:60:0,60,900 0/1:29,23:52:99:716,0,1023 0/0:22,0:22:60:0,60,795 0/0:20,0:20:60:0,60,741 0/0:20,0:20:60:0,60,711 0/0:24,0:24:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,731 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,736 0/0:30,0:30:65:0,65,990 +20 13269248 rs3827705 C T 101581.00 PASS HWP=0.1158;AC=21;culprit=FS;MQ0=0;ReadPosRankSum=0.755;AN=200;InbreedingCoeff=0.0639;AF=0.071;GQ_STDDEV=262.2;FS=0.0;DP=26063;GQ_MEAN=154.4;POSITIVE_TRAIN_SITE;VQSLOD=6.48;ClippingRankSum=-0.069;BaseQRankSum=-1.805;MLEAF=0.071;MLEAC=123;MQ=59.44;QD=14.26;DB;MQRankSum=0.592;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:82:0,82,1083 0/0:24,0:24:63:0,63,945 0/0:25,0:25:69:0,69,1035 0/0:23,0:23:60:0,60,851 0/0:21,0:21:60:0,60,900 0/0:33,0:33:73:0,73,1191 0/0:22,0:22:63:0,63,824 0/0:26,0:26:74:0,74,1125 0/0:25,0:25:69:0,69,1035 0/0:26,0:26:72:0,72,1080 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:63:0,63,945 0/0:35,0:35:93:0,93,1395 0/0:23,0:23:60:0,60,900 0/1:19,11:30:99:299,0,575 0/0:21,0:21:60:0,60,833 0/0:22,0:22:60:0,60,838 0/0:26,0:26:72:0,72,1068 0/1:24,15:39:99:421,0,720 0/1:30,25:55:99:744,0,854 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:67,70:137:99:2092,0,2239 0/1:89,80:169:99:2396,0,2770 0/0:20,0:20:60:0,60,753 0/1:24,28:52:99:782,0,732 0/1:20,32:52:99:958,0,514 0/0:21,0:21:63:0,63,767 0/0:25,0:25:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/1:44,50:94:99:1414,0,1324 0/0:30,0:30:73:0,73,964 0/0:26,0:26:63:0,63,913 0/0:24,0:24:66:0,66,883 0/0:22,0:22:63:0,63,772 0/1:35,34:69:99:950,0,1093 0/0:22,0:22:66:0,66,821 0/0:29,0:29:60:0,60,900 0/0:28,0:28:75:0,75,877 0/0:27,0:27:75:0,75,1013 0/0:24,0:24:63:0,63,921 0/0:23,0:23:60:0,60,900 0/0:23,0:23:63:0,63,945 0/1:24,21:45:99:615,0,709 0/0:29,0:29:75:0,75,1060 0/0:32,0:32:77:0,77,1121 0/0:24,0:24:60:0,60,889 0/0:23,0:23:61:0,61,856 0/0:33,0:33:78:0,78,1170 0/0:20,0:20:60:0,60,749 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:21,0:21:63:0,63,774 0/0:24,0:24:63:0,63,945 0/0:30,0:30:80:0,80,1160 0/0:24,0:24:66:0,66,776 0/0:29,0:29:77:0,77,1088 0/0:20,0:20:60:0,60,753 0/0:26,0:26:60:0,60,900 0/0:25,0:25:69:0,69,1006 0/0:28,0:28:67:0,67,1080 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,704 0/0:21,0:21:60:0,60,900 0/1:17,6:23:99:147,0,507 0/0:31,0:31:76:0,76,1170 0/0:33,0:33:70:0,70,1167 0/0:26,0:26:69:0,69,931 0/0:21,0:21:60:0,60,856 0/0:21,0:21:60:0,60,784 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,829 0/0:20,0:20:60:0,60,680 0/0:24,0:24:60:0,60,843 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,680 0/1:14,8:22:99:224,0,420 0/0:13,0:13:33:0,33,495 0/0:23,0:23:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:27,0:27:66:0,66,990 0/0:21,0:21:63:0,63,747 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,787 0/1:27,40:67:99:1109,0,809 0/0:26,0:26:66:0,66,990 0/0:31,0:31:87:0,87,1305 0/0:34,0:34:88:0,88,1129 0/0:23,0:23:60:0,60,900 0/1:17,17:34:99:489,0,552 0/0:25,0:25:69:0,69,1035 0/1:40,37:77:99:989,0,1203 0/0:31,0:31:73:0,73,1040 1/1:0,29:29:87:976,87,0 0/1:22,26:48:99:746,0,688 0/1:21,16:37:99:459,0,634 1/1:0,42:42:99:1421,126,0 +20 13279555 rs189481232 C T 1037.47 PASS HWP=1.0;AC=3;culprit=MQ;MQ0=0;ReadPosRankSum=0.636;AN=200;InbreedingCoeff=-0.0052;AF=0.002299;GQ_STDDEV=24.83;FS=0.0;DP=13430;GQ_MEAN=41.38;VQSLOD=4.14;ClippingRankSum=0.082;BaseQRankSum=-0.071;MLEAF=0.002299;MLEAC=4;MQ=60.0;QD=12.35;DB;MQRankSum=1.06;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:9,0:9:27:0,27,334 0/0:8,0:8:21:0,21,315 0/0:14,0:14:42:0,42,479 0/0:8,0:8:21:0,21,315 0/1:10,4:14:99:113,0,319 0/0:20,0:20:60:0,60,641 0/0:20,0:20:60:0,60,704 0/0:15,0:15:45:0,45,499 0/0:25,0:25:72:0,72,962 0/0:21,0:21:60:0,60,855 0/1:13,12:25:99:361,0,333 0/0:13,0:13:36:0,36,528 0/0:21,0:21:60:0,60,900 0/0:13,0:13:36:0,36,540 0/0:8,0:8:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,264 0/0:18,0:18:42:0,42,630 0/0:12,0:12:33:0,33,485 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:9,0:9:27:0,27,358 0/0:21,0:21:60:0,60,701 0/0:26,0:26:60:0,60,900 0/0:34,0:34:63:0,63,945 0/0:9,0:9:24:0,24,307 0/0:10,0:10:18:0,18,270 0/0:13,0:13:28:0,28,450 0/0:21,0:21:60:0,60,762 0/0:24,0:24:60:0,60,887 0/0:14,0:14:34:0,34,443 0/0:24,0:24:60:0,60,900 0/0:12,0:12:23:0,23,344 0/0:23,0:23:60:0,60,900 0/1:14,15:29:99:430,0,429 0/0:8,0:8:21:0,21,315 0/0:10,0:10:27:0,27,405 0/0:11,0:11:27:0,27,405 0/0:14,0:14:27:0,27,405 0/0:13,0:13:30:0,30,450 0/0:7,0:7:15:0,15,225 0/0:10,0:10:27:0,27,340 0/0:9,0:9:27:0,27,340 0/0:7,0:7:21:0,21,208 0/0:10,0:10:24:0,24,335 0/0:10,0:10:24:0,24,354 0/0:11,0:11:30:0,30,400 0/0:8,0:8:21:0,21,285 0/0:7,0:7:21:0,21,297 0/0:11,0:11:30:0,30,450 0/0:11,0:11:33:0,33,399 0/0:7,0:7:21:0,21,212 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,311 0/0:10,0:10:30:0,30,339 0/0:13,0:13:39:0,39,497 0/0:7,0:7:21:0,21,261 0/0:10,0:10:20:0,20,360 0/0:8,0:8:24:0,24,263 0/0:7,0:7:21:0,21,281 0/0:11,0:11:27:0,27,405 0/0:13,0:13:26:0,26,461 0/0:17,0:17:13:0,13,590 0/0:6,0:6:12:0,12,180 0/0:8,0:8:21:0,21,315 0/0:12,0:12:33:0,33,467 0/0:6,0:6:15:0,15,190 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,301 0/0:7,0:7:21:0,21,200 0/0:8,0:8:21:0,21,290 0/0:7,0:7:21:0,21,255 0/0:10,0:10:21:0,21,315 0/0:6,0:6:7:0,7,192 0/0:8,0:8:24:0,24,320 0/0:5,0:5:15:0,15,186 0/0:7,0:7:21:0,21,289 0/0:7,0:7:21:0,21,253 0/0:7,0:7:21:0,21,257 0/0:9,0:9:21:0,21,315 0/0:2,0:2:6:0,6,73 0/0:4,0:4:12:0,12,130 0/0:7,0:7:21:0,21,203 0/0:4,0:4:12:0,12,157 0/0:3,0:3:9:0,9,86 0/0:8,0:8:21:0,21,297 0/0:21,0:21:60:0,60,707 0/0:22,0:22:60:0,60,900 0/0:12,0:12:33:0,33,397 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,759 0/0:17,0:17:51:0,51,522 0/0:8,0:8:21:0,21,292 0/0:7,0:7:21:0,21,210 0/0:21,0:21:60:0,60,900 0/0:17,0:17:11:0,11,457 0/0:8,0:8:24:0,24,232 0/0:9,0:9:18:0,18,270 0/0:7,0:7:21:0,21,240 0/0:3,0:3:9:0,9,106 +20 13279957 . T C 287.70 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.4;AN=200;InbreedingCoeff=-0.0011;AF=5.747E-4;GQ_STDDEV=15.37;FS=0.0;DP=18769;GQ_MEAN=58.26;VQSLOD=4.98;ClippingRankSum=-0.4;BaseQRankSum=2.4;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=20.55;MQRankSum=0.8;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:13,0:13:24:0,24,401 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,718 0/0:21,0:21:60:0,60,766 0/0:28,0:28:75:0,75,1075 0/0:24,0:24:60:0,60,860 0/0:21,0:21:60:0,60,801 0/0:23,0:23:63:0,63,890 0/0:24,0:24:66:0,66,917 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:18,0:18:20:0,20,663 0/0:22,0:22:60:0,60,900 0/0:10,0:10:24:0,24,360 0/0:20,0:20:60:0,60,725 0/0:21,0:21:60:0,60,725 0/0:22,0:22:60:0,60,830 0/0:23,0:23:63:0,63,914 0/0:25,0:25:69:0,69,1023 0/0:20,0:20:60:0,60,687 0/0:23,0:23:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:66:0,66,808 0/0:28,0:28:72:0,72,1013 0/0:20,0:20:60:0,60,729 0/0:20,0:20:60:0,60,639 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:14,0:14:42:0,42,468 0/0:23,0:23:63:0,63,945 0/0:24,0:24:61:0,61,833 0/0:21,0:21:63:0,63,794 0/0:28,0:28:69:0,69,1027 0/0:20,0:20:60:0,60,693 0/0:20,0:20:60:0,60,696 0/0:18,0:18:48:0,48,720 0/0:24,0:24:63:0,63,945 0/0:30,0:30:67:0,67,1080 0/0:28,0:28:84:0,84,1010 0/0:22,0:22:63:0,63,917 0/0:26,0:26:66:0,66,990 0/0:21,0:21:60:0,60,769 0/0:21,0:21:60:0,60,753 0/0:26,0:26:78:0,78,982 0/0:21,0:21:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:29,0:29:87:0,87,1063 0/0:23,0:23:63:0,63,881 0/0:24,0:24:66:0,66,988 0/0:22,0:22:60:0,60,900 0/0:7,0:7:21:0,21,249 0/0:20,0:20:60:0,60,731 0/0:26,0:26:72:0,72,1080 0/0:38,0:38:88:0,88,1440 0/0:23,0:23:62:0,62,925 0/0:27,0:27:40:0,40,1010 0/0:25,0:25:60:0,60,891 0/0:23,0:23:60:0,60,864 0/0:21,0:21:60:0,60,847 0/0:23,0:23:63:0,63,878 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,752 0/0:7,0:7:21:0,21,287 0/0:7,0:7:21:0,21,249 0/0:22,0:22:60:0,60,857 0/0:5,0:5:12:0,12,180 0/0:22,0:22:63:0,63,786 0/0:22,0:22:51:0,51,765 0/0:22,0:22:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:9,0:9:25:0,25,343 0/0:9,0:9:24:0,24,360 0/0:7,0:7:21:0,21,274 0/0:7,0:7:21:0,21,291 0/0:11,0:11:33:0,33,418 0/0:8,0:8:21:0,21,285 0/0:7,0:7:21:0,21,291 0/0:7,0:7:21:0,21,241 0/0:7,0:7:21:0,21,251 0/0:15,0:15:45:0,45,557 0/0:8,0:8:24:0,24,297 0/0:20,0:20:60:0,60,769 0/0:25,0:25:72:0,72,852 0/0:20,0:20:60:0,60,648 0/0:21,0:21:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:20,0:20:60:0,60,842 0/0:20,0:20:60:0,60,677 0/0:9,0:9:24:0,24,360 0/0:10,0:10:30:0,30,369 0/0:22,0:22:60:0,60,782 0/0:29,0:29:72:0,72,1080 0/0:8,0:8:21:0,21,315 0/1:5,9:14:99:338,0,143 0/0:4,0:4:9:0,9,135 0/0:22,0:22:60:0,60,900 diff --git a/hail/python/hail/docs/data/samplepart2.vcf b/hail/python/hail/docs/data/samplepart2.vcf new file mode 100644 index 00000000000..ece1a8c762c --- /dev/null +++ b/hail/python/hail/docs/data/samplepart2.vcf @@ -0,0 +1,170 @@ +##fileformat=VCFv4.2 +##fileDate=2016-01-28 +##source=Hailv0.0 +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT C1046::HG02024 C1046::HG02025 C1046::HG02026 C1047::HG00731 C1047::HG00732 C1047::HG00733 C1048::HG02024 C1048::HG02025 C1048::HG02026 C1049::HG00731 C1049::HG00732 C1049::HG00733 C1050::HG03006 C1051::HG03642 C1589::HG02922 C1589::HG03006 C1589::HG03052 C1589::HG03642 C1589::NA12878 C1589::NA19017 C1589::NA19625 C1589::NA19648 C1589::NA20845 C339::NA12878 C339::NA12891 C454::NA19625 C456::NA12878 C456::NA12891 C464::NA20845 C469::HG02025 C469::HG02026 C470::NA19017 C474::NA19648 C477::HG00731 C477::HG00732 C958::HG03052 C959::HG02922 HG00096 HG00100 HG00116 HG00117 HG00119 HG00120 HG00123 HG00124 HG00131 HG00133 HG00145 HG00146_A1 HG00155_A1 HG00157 HG00158 HG00159 HG00160 HG00176 HG00239 HG00242 HG00243 HG00244 HG00245_A1 HG00255 HG00258 HG00262 HG00264 HG00265 HG00268 HG00272 HG00306 HG00308 HG00311 HG00312 HG00357 HG00361 HG00366 HG00367 HG00368 HG00369 HG00371 HG00372 HG00373 HG00377 HG00379 HG00380 HG00384 HG00403 HG00404 HG00409 HG00410 HG00419 HG00551 HG00598 HG00599 HG00610 HG00611 HG00622 HG00623 HG00625 HG00626 HG00628 HG00629 +20 13371103 . CAG C 1120.86 VQSRTrancheINDEL99.00to99.50 HWP=1.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=0.241;AN=200;InbreedingCoeff=-0.019;AF=0.013;GQ_STDDEV=20.71;FS=4.63;DP=21637;GQ_MEAN=50.43;VQSLOD=-0.5555;ClippingRankSum=-0.436;BaseQRankSum=-0.37;MLEAF=0.013;MLEAC=22;MQ=59.59;QD=1.15;MQRankSum=0.513;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,779 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,846 0/0:37,0:37:3:0,3,1159 0/0:27,0:27:66:0,66,990 0/1:27,4:31:65:65,0,944 0/0:32,0:32:54:0,54,1118 0/0:20,0:20:60:0,60,821 0/0:27,0:27:61:0,61,945 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,778 0/0:34,0:34:15:0,15,1007 0/0:24,0:24:67:0,67,1035 0/0:14,0:14:27:0,27,495 0/0:20,0:20:54:0,54,810 0/0:8,0:8:21:0,21,315 0/0:33,0:33:57:0,57,1113 0/0:11,0:11:21:0,21,315 0/0:28,0:28:44:0,44,855 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,822 0/0:24,0:24:31:0,31,789 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,873 0/0:22,0:22:17:0,17,737 0/0:57,0:57:22:0,22,1823 0/0:31,0:31:67:0,67,1170 0/0:35,0:35:78:0,78,1170 0/0:31,0:31:65:0,65,1125 0/0:20,0:20:60:0,60,736 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,856 0/0:27,0:27:63:0,63,945 0/0:17,0:17:25:0,25,517 0/0:24,0:24:63:0,63,945 0/0:29,0:29:61:0,61,990 0/0:26,0:26:38:0,38,900 0/0:27,0:27:72:0,72,1070 0/0:27,0:27:66:0,66,914 0/0:24,0:24:63:0,63,945 0/0:21,0:21:63:0,63,774 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,879 0/0:15,0:15:29:0,29,495 0/0:25,0:25:33:0,33,836 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,833 0/0:30,0:30:52:0,52,1100 0/0:26,0:26:69:0,69,1035 0/0:20,0:20:60:0,60,773 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,853 0/0:23,0:23:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:29,0:29:38:0,38,984 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:11,0:11:23:0,23,368 0/0:27,0:27:66:0,66,990 0/0:19,0:19:11:0,11,656 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:28,0:28:66:0,66,1015 0/0:20,0:20:60:0,60,778 0/0:25,0:25:60:0,60,900 0/0:9,0:9:23:0,23,311 0/0:9,0:9:20:0,20,315 0/0:23,0:23:51:0,51,765 0/0:12,0:12:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,279 0/0:11,0:11:21:0,21,315 0/0:10,0:10:18:0,18,270 0/0:15,0:15:36:0,36,540 0/0:10,0:10:24:0,24,360 0/0:31,0:31:56:0,56,1152 0/0:20,0:20:60:0,60,732 0/0:21,0:21:60:0,60,795 0/0:14,0:14:30:0,30,450 0/0:30,0:30:69:0,69,1035 0/0:83,0:83:30:0,30,2447 0/0:21,0:21:63:0,63,810 0/0:25,0:25:66:0,66,925 0/0:8,0:8:21:0,21,285 0/0:51,0:51:36:0,36,1589 0/0:20,0:20:60:0,60,803 0/0:13,0:13:33:0,33,495 0/0:9,0:9:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:26,0:26:60:0,60,900 +20 13371117 rs189198853 C T 275.73 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.619;AN=200;InbreedingCoeff=-0.0025;AF=5.747E-4;GQ_STDDEV=20.27;FS=0.0;DP=18049;GQ_MEAN=50.43;POSITIVE_TRAIN_SITE;VQSLOD=4.72;ClippingRankSum=-0.784;BaseQRankSum=-2.931;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=14.51;DB;MQRankSum=1.28;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:54:0,54,810 0/0:21,0:21:60:0,60,779 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,846 0/0:25,0:25:66:0,66,990 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:20,0:20:20:0,20,712 0/0:20,0:20:60:0,60,821 0/0:27,0:27:61:0,61,945 0/0:29,0:29:48:0,48,1169 0/0:22,0:22:60:0,60,778 0/0:24,0:24:60:0,60,900 0/0:24,0:24:67:0,67,1035 0/0:14,0:14:27:0,27,495 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:28,0:28:60:0,60,900 0/0:7,0:7:21:0,21,245 0/0:16,0:16:30:0,30,450 0/0:15,0:15:31:0,31,495 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,822 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,873 0/0:12,0:12:36:0,36,462 0/0:29,0:29:75:0,75,1125 0/0:31,0:31:67:0,67,1170 0/0:35,0:35:78:0,78,1170 0/0:31,0:31:65:0,65,1125 0/0:20,0:20:60:0,60,736 0/0:22,0:22:60:0,60,900 0/0:13,0:13:33:0,33,482 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,856 0/0:16,0:16:39:0,39,585 0/0:17,0:17:25:0,25,517 0/0:26,0:26:60:0,60,900 0/0:29,0:29:61:0,61,990 0/0:24,0:24:60:0,60,900 0/0:27,0:27:72:0,72,1070 0/0:27,0:27:66:0,66,914 0/0:17,0:17:33:0,33,547 0/0:21,0:21:63:0,63,774 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,879 0/0:15,0:15:29:0,29,495 0/0:13,0:13:22:0,22,387 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,833 0/0:28,0:28:63:0,63,945 0/0:17,0:17:32:0,32,564 0/0:30,0:30:58:0,58,1099 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,853 0/0:23,0:23:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:23,0:23:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:9,0:9:21:0,21,315 0/0:11,0:11:23:0,23,368 0/0:27,0:27:66:0,66,990 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:26,0:26:53:0,53,914 0/0:28,0:28:66:0,66,1015 0/0:12,0:12:24:0,24,360 0/0:12,0:12:24:0,24,360 0/0:9,0:9:23:0,23,311 0/0:3,0:3:6:0,6,90 0/0:24,0:24:60:0,60,900 0/0:13,0:13:2:0,2,470 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,279 0/0:11,0:11:21:0,21,315 0/0:3,0:3:9:0,9,116 0/0:16,0:16:8:0,8,595 0/0:10,0:10:24:0,24,360 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,732 0/0:21,0:21:60:0,60,795 0/0:14,0:14:30:0,30,450 0/0:30,0:30:69:0,69,1035 0/0:34,0:34:66:0,66,990 0/0:21,0:21:63:0,63,810 0/1:8,11:19:99:326,0,274 0/0:8,0:8:21:0,21,285 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,803 0/0:13,0:13:33:0,33,495 0/0:9,0:9:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:10,0:10:24:0,24,360 +20 13463855 rs2273479 T C 226557.00 PASS HWP=0.6992;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.423;AN=200;InbreedingCoeff=0.019;AF=0.075;GQ_STDDEV=518.01;FS=0.0;DP=51143;GQ_MEAN=288.31;POSITIVE_TRAIN_SITE;VQSLOD=6.7;ClippingRankSum=-0.128;BaseQRankSum=2.01;MLEAF=0.075;MLEAC=130;MQ=59.67;QD=17.42;DB;MQRankSum=0.105;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:45,0:45:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:42,0:42:87:0,87,1305 0/0:51,0:51:99:0,120,1800 0/0:50,0:50:99:0,103,1800 0/0:69,0:69:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:42,0:42:89:0,89,1588 0/0:49,0:49:99:0,120,1800 0/0:38,0:38:99:0,108,1620 0/0:49,0:49:99:0,114,1710 0/0:39,0:39:96:0,96,1440 0/0:37,0:37:99:0,105,1575 0/0:41,0:41:88:0,88,1440 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/0:74,0:74:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:36,0:36:99:0,99,1485 0/0:78,0:78:98:0,98,1800 0/0:102,0:102:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:32,0:32:72:0,72,1080 0/0:37,0:37:63:0,63,945 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:90:0,90,1733 0/0:75,0:75:99:0,120,1800 0/0:35,0:35:73:0,73,1125 0/0:37,0:37:76:0,76,1435 0/0:47,0:47:99:0,120,1800 0/0:43,0:43:73:0,73,1800 0/0:64,0:64:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:72,0:72:99:0,104,1800 0/0:102,0:102:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:35,0:35:99:0,99,1485 0/0:32,0:32:67:0,67,1305 0/0:41,0:41:99:0,108,1620 0/0:56,0:56:99:0,114,1710 0/0:43,0:43:99:0,111,1665 0/0:57,0:57:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:98,0:98:99:0,120,1800 0/0:50,0:50:85:0,85,1800 0/0:51,0:51:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/1:45,45:90:99:1502,0,1459 0/0:70,0:70:99:0,120,1800 0/0:28,0:28:75:0,75,1125 0/0:28,0:28:81:0,81,1215 0/0:106,0:106:99:0,120,1800 0/0:33,0:33:90:0,90,1350 0/0:81,0:81:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:34,0:34:81:0,81,1395 0/0:44,0:44:99:0,120,1800 0/0:41,0:41:99:0,111,1665 0/0:42,0:42:95:0,95,1710 0/0:26,0:26:75:0,75,1000 0/0:44,0:44:99:0,120,1800 0/0:38,0:38:99:0,108,1620 0/0:39,0:39:96:0,96,1440 0/0:33,0:33:81:0,81,1215 0/0:25,0:25:69:0,69,1035 0/0:41,0:41:97:0,97,1638 0/0:59,0:59:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:26,0:26:75:0,75,1125 0/0:34,0:34:72:0,72,1080 0/0:40,0:40:99:0,100,1471 0/0:75,0:75:99:0,111,1800 0/0:45,0:45:99:0,102,1530 0/1:56,62:118:99:1960,0,1734 0/0:35,0:35:99:0,99,1485 0/0:30,0:30:84:0,84,1260 0/0:27,0:27:75:0,75,1125 0/0:27,0:27:72:0,72,1080 0/0:42,0:42:72:0,72,1710 0/0:46,0:46:99:0,120,1800 0/0:28,0:28:66:0,66,1016 0/0:51,0:51:99:0,105,1710 +20 13463948 . C T 2693.48 VQSRTrancheSNP99.95to100.00 HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=-5.885;AN=200;InbreedingCoeff=-0.0259;AF=0.00977;GQ_STDDEV=38.64;FS=187.175;DP=51955;GQ_MEAN=90.21;VQSLOD=-305.7;ClippingRankSum=-1.116;BaseQRankSum=-5.871;MLEAF=0.00977;MLEAC=17;MQ=59.55;QD=1.15;MQRankSum=0.055;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:45,0:45:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:42,0:42:87:0,87,1305 0/0:51,0:51:99:0,120,1800 0/0:50,0:50:99:0,103,1800 0/0:69,0:69:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:42,0:42:89:0,89,1588 0/0:49,0:49:99:0,120,1800 0/0:38,0:38:99:0,108,1620 0/0:49,0:49:99:0,114,1710 0/0:39,0:39:96:0,96,1440 0/0:37,0:37:99:0,105,1575 0/0:41,0:41:88:0,88,1440 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/0:74,0:74:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/1:77,20:97:99:133,0,2228 0/0:89,0:89:0:0,0,2121 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:36,0:36:99:0,99,1485 0/0:78,0:78:98:0,98,1800 0/0:182,0:182:0:0,0,5435 0/0:150,0:150:20:0,20,4475 0/0:32,0:32:72:0,72,1080 0/0:37,0:37:63:0,63,945 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:90:0,90,1733 0/0:75,0:75:99:0,120,1800 0/0:35,0:35:73:0,73,1125 0/0:37,0:37:76:0,76,1435 0/0:82,0:82:6:0,6,2336 0/0:43,0:43:73:0,73,1800 0/0:64,0:64:99:0,120,1800 0/0:107,0:107:0:0,0,2742 0/0:63,0:63:99:0,120,1800 0/0:98,0:98:0:0,0,2410 0/0:72,0:72:99:0,104,1800 0/0:164,27:191:99:0,110,5139 0/0:85,0:85:26:0,26,2456 0/0:82,0:82:51:0,51,2416 0/0:32,0:32:67:0,67,1305 0/0:120,0:120:0:0,0,3405 0/0:56,0:56:99:0,114,1710 0/0:43,0:43:99:0,111,1665 0/0:57,0:57:99:0,120,1800 0/0:97,0:97:0:0,0,2779 0/0:112,0:112:0:0,0,3006 0/0:98,0:98:99:0,120,1800 0/0:50,0:50:85:0,85,1800 0/0:109,0:109:2:0,2,3109 0/0:200,0:200:0:0,0,5668 0/0:94,0:94:0:0,0,2220 0/0:80,0:80:99:0,119,1800 0/0:70,0:70:99:0,120,1800 0/0:69,0:69:0:0,0,1969 0/1:59,15:74:87:87,0,1759 0/0:106,0:106:99:0,120,1800 0/0:80,19:99:15:0,15,2302 0/0:81,0:81:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:34,0:34:81:0,81,1395 0/0:87,0:87:58:0,58,2677 0/0:76,0:76:0:0,0,2262 0/0:91,0:91:42:0,42,2919 0/0:90,0:90:0:0,0,2329 0/0:98,0:98:10:0,10,2753 0/0:84,22:106:22:0,22,2650 0/0:65,0:65:31:0,31,1978 0/0:96,0:96:0:0,0,2676 0/0:71,0:71:32:0,32,2244 0/0:41,0:41:97:0,97,1638 0/0:102,0:102:58:0,58,3184 0/0:61,0:61:99:0,120,1800 0/0:26,0:26:75:0,75,1125 0/0:34,0:34:72:0,72,1080 0/0:40,0:40:99:0,100,1471 0/0:75,0:75:99:0,111,1800 0/0:45,0:45:99:0,102,1530 0/0:51,0:51:99:0,102,1530 0/0:92,0:92:0:0,0,2547 0/0:76,0:76:39:0,39,2281 0/0:27,0:27:75:0,75,1125 0/0:27,0:27:72:0,72,1080 0/0:42,0:42:72:0,72,1710 0/0:90,17:107:85:0,85,2861 0/0:69,0:69:0:0,0,1840 0/0:51,0:51:99:0,105,1710 +20 13464014 rs45602236 G A 52754.50 PASS HWP=1.0;AC=3;culprit=MQ;MQ0=0;ReadPosRankSum=0.356;AN=200;InbreedingCoeff=0.013;AF=0.028;GQ_STDDEV=256.63;FS=1.396;DP=48205;GQ_MEAN=151.69;POSITIVE_TRAIN_SITE;VQSLOD=4.86;ClippingRankSum=0.21;BaseQRankSum=-4.464;MLEAF=0.028;MLEAC=49;MQ=60.0;QD=14.27;DB;MQRankSum=0.363;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:45,0:45:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:42,0:42:87:0,87,1305 0/1:44,31:75:99:894,0,1432 0/0:50,0:50:99:0,103,1800 0/0:69,0:69:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:42,0:42:89:0,89,1588 0/0:49,0:49:99:0,120,1800 0/1:47,26:73:99:678,0,1526 0/0:49,0:49:99:0,114,1710 0/0:39,0:39:96:0,96,1440 0/0:37,0:37:99:0,105,1575 0/0:41,0:41:88:0,88,1440 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/0:74,0:74:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:36,0:36:99:0,99,1485 0/0:78,0:78:98:0,98,1800 0/1:72,78:150:99:2464,0,2471 0/0:82,0:82:99:0,120,1800 0/0:32,0:32:72:0,72,1080 0/0:37,0:37:63:0,63,945 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:90:0,90,1733 0/0:75,0:75:99:0,120,1800 0/0:35,0:35:73:0,73,1125 0/0:37,0:37:76:0,76,1435 0/0:69,0:69:99:0,120,1800 0/0:43,0:43:73:0,73,1800 0/0:64,0:64:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:72,0:72:99:0,104,1800 0/0:104,0:104:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:32,0:32:67:0,67,1305 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,114,1710 0/0:43,0:43:99:0,111,1665 0/0:57,0:57:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:102,0:102:99:0,120,1800 0/0:98,0:98:99:0,120,1800 0/0:50,0:50:85:0,85,1800 0/0:73,0:73:99:0,120,1800 0/0:129,0:129:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:80,0:80:99:0,119,1800 0/0:70,0:70:99:0,120,1800 0/0:34,0:34:69:0,69,1035 0/0:47,0:47:99:0,114,1710 0/0:106,0:106:99:0,120,1800 0/0:41,0:41:99:0,111,1665 0/0:81,0:81:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:34,0:34:81:0,81,1395 0/0:57,0:57:99:0,120,1800 0/0:34,0:34:81:0,81,1260 0/0:51,0:51:99:0,111,1665 0/0:54,0:54:99:0,120,1800 0/0:34,0:34:72:0,72,1305 0/0:49,0:49:93:0,93,1395 0/0:38,0:38:84:0,84,1260 0/0:35,0:35:81:0,81,1215 0/0:29,0:29:72:0,72,1080 0/0:41,0:41:97:0,97,1638 0/0:65,0:65:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:26,0:26:75:0,75,1125 0/0:34,0:34:72:0,72,1080 0/0:40,0:40:99:0,100,1471 0/0:75,0:75:99:0,111,1800 0/0:45,0:45:99:0,102,1530 0/0:51,0:51:99:0,102,1530 0/0:48,0:48:99:0,120,1800 0/0:44,0:44:99:0,99,1485 0/0:27,0:27:75:0,75,1125 0/0:27,0:27:72:0,72,1080 0/0:42,0:42:72:0,72,1710 0/0:62,0:62:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/0:51,0:51:99:0,105,1710 +20 13464030 rs2273480 C A 507357.00 PASS HWP=0.3022;AC=71;culprit=QD;MQ0=0;ReadPosRankSum=0.324;AN=200;InbreedingCoeff=0.0369;AF=0.284;GQ_STDDEV=469.26;FS=3.01;DP=50317;GQ_MEAN=409.13;POSITIVE_TRAIN_SITE;VQSLOD=4.34;ClippingRankSum=-0.178;BaseQRankSum=-4.651;MLEAF=0.284;MLEAC=495;MQ=59.84;QD=19.14;DB;MQRankSum=0.081;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:45,0:45:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/1:19,21:40:99:598,0,644 0/0:55,0:55:99:0,120,1800 0/0:50,0:50:99:0,103,1800 0/0:69,0:69:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:42,0:42:89:0,89,1588 0/1:36,38:74:99:1168,0,1259 0/0:59,0:59:99:0,120,1800 0/0:49,0:49:99:0,114,1710 0/0:39,0:39:96:0,96,1440 0/1:23,18:41:99:546,0,836 0/0:41,0:41:88:0,88,1440 0/1:21,16:37:99:460,0,614 0/1:34,46:80:99:1426,0,1028 0/0:39,0:39:81:0,81,1215 0/0:61,0:61:99:0,120,1800 0/1:42,33:75:99:961,0,1301 0/0:66,0:66:99:0,120,1800 0/1:36,28:64:99:820,0,1165 0/1:31,33:64:99:1003,0,1000 0/0:54,0:54:99:0,117,1755 0/1:41,57:98:99:1917,0,1475 0/0:69,0:69:99:0,120,1800 0/1:43,28:71:99:831,0,1512 0/1:34,38:72:99:1244,0,1116 0/0:62,0:62:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/1:45,51:96:99:1422,0,1541 0/0:36,0:36:99:0,99,1485 0/1:50,46:96:99:1370,0,1825 0/0:108,0:108:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:32,0:32:72:0,72,1080 0/1:21,15:36:99:431,0,749 0/0:56,0:56:99:0,120,1800 1/1:0,64:64:99:2394,192,0 0/0:75,0:75:99:0,120,1800 0/0:35,0:35:73:0,73,1125 0/0:37,0:37:76:0,76,1435 0/1:38,27:65:99:779,0,1368 0/1:34,33:67:99:1065,0,1206 0/0:64,0:64:99:0,120,1800 0/1:44,24:68:99:683,0,1585 0/0:63,0:63:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/1:56,49:105:99:1567,0,2031 1/1:0,105:105:99:4038,316,0 0/0:72,0:72:99:0,120,1800 0/1:29,34:63:99:1052,0,999 0/1:27,21:48:99:654,0,944 0/1:29,22:51:99:655,0,1106 0/1:26,28:54:99:883,0,946 0/0:43,0:43:99:0,111,1665 0/1:33,48:81:99:1583,0,1074 1/1:0,76:76:99:2912,229,0 1/1:0,99:99:99:3759,298,0 1/1:0,132:132:99:4984,397,0 0/1:36,32:68:99:983,0,1228 0/1:28,46:74:99:1501,0,924 1/1:0,124:124:99:4587,373,0 0/1:35,23:58:99:691,0,1268 0/1:39,39:78:99:1224,0,1373 0/0:70,0:70:99:0,120,1800 0/1:17,18:35:99:550,0,635 1/1:0,47:47:99:1744,141,0 1/1:0,116:116:99:4379,349,0 0/1:26,18:44:99:507,0,1031 0/0:81,0:81:99:0,120,1800 1/1:0,58:58:99:2167,175,0 0/0:83,0:83:99:0,120,1800 0/0:34,0:34:81:0,81,1395 0/1:28,28:56:99:864,0,1053 0/0:34,0:34:81:0,81,1260 0/1:21,30:51:99:955,0,785 0/1:25,26:51:99:813,0,942 0/0:34,0:34:72:0,72,1305 0/1:16,31:47:99:1009,0,532 0/1:19,17:36:99:521,0,746 0/1:12,21:33:99:691,0,417 0/0:29,0:29:72:0,72,1080 0/0:41,0:41:97:0,97,1638 0/1:38,25:63:99:754,0,1457 0/0:61,0:61:99:0,120,1800 1/1:0,41:41:99:1521,123,0 0/1:15,20:35:99:598,0,528 0/1:28,30:58:99:938,0,895 1/1:0,93:93:99:3432,280,0 0/1:23,27:50:99:826,0,762 0/0:51,0:51:99:0,102,1530 0/1:23,24:47:99:777,0,881 1/1:0,46:46:99:1701,138,0 0/1:21,14:35:99:411,0,723 1/1:0,33:33:99:1147,99,0 0/1:26,20:46:99:608,0,961 0/1:32,33:65:99:1030,0,1208 0/1:17,16:33:99:496,0,656 0/1:25,31:56:99:981,0,913 +20 13509135 . G C 30.02 VQSRTrancheSNP99.80to99.90 NEGATIVE_TRAIN_SITE;HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=-1.468;AN=198;InbreedingCoeff=-0.0558;AF=5.767E-4;GQ_STDDEV=27.3;FS=19.956;DP=16181;GQ_MEAN=37.64;VQSLOD=-5.426;ClippingRankSum=1.24;BaseQRankSum=-1.932;MLEAF=5.767E-4;MLEAC=1;MQ=58.98;QD=2.5;MQRankSum=0.6;CCC=1734;NCC=3 GT:AD:DP:GQ:PL 0/0:24,0:24:63:0,63,835 0/0:12,0:12:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,702 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,864 0/0:13,0:13:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:13,0:13:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:21,0:21:60:0,60,709 0/0:8,0:8:21:0,21,265 0/0:9,0:9:24:0,24,316 0/0:15,0:15:27:0,27,405 0/0:24,0:24:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,277 0/0:8,0:8:21:0,21,315 0/0:21,0:21:17:0,17,755 0/0:16,0:16:33:0,33,495 0/0:10,0:10:0:0,0,236 0/0:10,0:10:0:0,0,211 0/0:14,0:14:0:0,0,205 0/0:34,0:34:69:0,69,1035 0/0:37,0:37:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:21,0:21:60:0,60,759 0/0:11,0:11:0:0,0,155 0/0:15,0:15:18:0,18,270 0/0:14,0:14:8:0,8,135 0/0:20,0:20:60:0,60,626 0/0:27,0:27:63:0,63,945 0/0:20,0:20:22:0,22,629 0/0:8,0:8:0:0,0,238 0/0:12,0:12:4:0,4,362 0/0:7,0:7:0:0,0,63 0/0:4,0:4:6:0,6,90 0/0:8,0:8:12:0,12,180 0/0:6,0:6:0:0,0,122 0/0:5,0:5:0:0,0,36 0/0:8,0:8:0:0,0,1 0/0:7,0:7:9:0,9,135 0/0:12,0:12:0:0,0,340 0/0:7,0:7:0:0,0,218 0/0:13,0:13:18:0,18,270 0/0:9,0:9:0:0,0,224 0/0:7,0:7:0:0,0,65 0/0:8,0:8:0:0,0,111 0/0:7,0:7:9:0,9,135 0/0:13,0:13:9:0,9,335 0/0:9,0:9:0:0,0,173 0/0:17,0:17:0:0,0,387 0/0:10,0:10:0:0,0,221 0/0:14,0:14:0:0,0,192 0/0:10,0:10:15:0,15,225 0/0:4,0:4:12:0,12,155 0/0:9,0:9:0:0,0,165 0/0:6,0:6:6:0,6,90 0/0:10,0:10:0:0,0,103 0/0:13,0:13:0:0,0,282 0/0:16,0:16:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:3,0:3:9:0,9,114 0/0:14,0:14:6:0,6,440 0/0:7,0:7:0:0,0,160 0/0:6,0:6:9:0,9,135 0/0:7,0:7:0:0,0,156 0/0:18,0:18:30:0,30,450 0/0:9,0:9:0:0,0,263 0/0:9,0:9:0:0,0,254 0/0:7,0:7:0:0,0,231 0/0:11,0:11:0:0,0,263 0/0:8,0:8:9:0,9,135 0/0:5,0:5:0:0,0,99 0/0:8,0:8:0:0,0,196 0/0:8,0:8:0:0,0,131 0/0:6,0:6:12:0,12,180 0/0:9,0:9:12:0,12,180 0/0:6,0:6:12:0,12,180 0/0:11,0:11:12:0,12,180 0/0:16,0:16:33:0,33,495 0/0:21,0:21:63:0,63,741 0/0:20,0:20:60:0,60,762 0/0:7,0:7:21:0,21,259 0/0:12,0:12:12:0,12,180 0/0:25,0:25:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:3,0:3:6:0,6,90 0/1:8,4:12:78:78,0,259 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,675 0/0:6,0:6:9:0,9,135 0/0:6,0:6:0:0,0,102 0/0:8,0:8:21:0,21,315 ./.:5,0:5:.:. +20 13514662 rs77527408 T C 31025.20 PASS HWP=1.0;AC=4;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.822;AN=200;InbreedingCoeff=-0.0081;AF=0.008046;GQ_STDDEV=256.31;FS=1.237;DP=55823;GQ_MEAN=137.75;POSITIVE_TRAIN_SITE;VQSLOD=4.48;ClippingRankSum=-0.646;BaseQRankSum=5.75;MLEAF=0.008046;MLEAC=14;MQ=59.74;QD=15.45;DB;MQRankSum=0.468;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:55,0:55:99:0,120,1800 0/0:50,0:50:99:0,105,1575 0/0:48,0:48:99:0,117,1755 0/0:58,0:58:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:52,0:52:99:0,111,1665 0/0:65,0:65:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:34,0:34:70:0,70,1125 0/0:36,0:36:81:0,81,1215 0/0:37,0:37:87:0,87,1305 0/1:50,61:111:99:1769,0,1246 0/0:43,0:43:96:0,96,1440 0/0:37,0:37:87:0,87,1305 0/0:38,0:38:81:0,81,1215 0/0:59,0:59:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:79,63:142:99:1890,0,2198 0/0:116,0:116:99:0,120,1800 0/0:145,0:145:99:0,120,1800 0/0:127,0:127:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:41,0:41:99:0,99,1485 0/0:65,0:65:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/1:66,60:126:99:1972,0,1951 0/0:93,0:93:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:110,0:110:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:108,0:108:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/1:52,58:110:99:1930,0,1478 0/0:129,0:129:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:40,0:40:81:0,81,1395 0/0:34,0:34:66:0,66,990 0/0:28,0:28:66:0,66,990 0/0:107,0:107:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/0:68,0:68:99:0,120,1800 0/0:51,0:51:81:0,81,1215 0/0:76,0:76:99:0,120,1800 0/0:39,0:39:96:0,96,1440 0/0:45,0:45:99:0,105,1575 0/0:37,0:37:84:0,84,1260 0/0:44,0:44:99:0,120,1800 0/0:44,0:44:99:0,99,1485 0/0:63,0:63:99:0,120,1800 0/0:46,0:46:99:0,108,1620 0/0:39,0:39:79:0,79,1440 0/0:32,0:32:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:51,0:51:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:46,0:46:99:0,108,1620 0/0:102,0:102:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:34,0:34:75:0,75,1125 0/0:47,0:47:99:0,108,1620 0/0:32,0:32:69:0,69,1035 0/0:64,0:64:99:0,120,1800 +20 13514699 rs145022707 C T 7927.93 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.313;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=107.56;FS=2.603;DP=55092;GQ_MEAN=116.59;POSITIVE_TRAIN_SITE;VQSLOD=4.03;ClippingRankSum=-0.367;BaseQRankSum=-2.683;MLEAF=0.002874;MLEAC=5;MQ=60.0;QD=14.18;DB;MQRankSum=-0.29;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:55,0:55:99:0,120,1800 0/0:50,0:50:99:0,105,1575 0/0:48,0:48:99:0,117,1755 0/0:58,0:58:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:52,0:52:99:0,111,1665 0/0:65,0:65:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:34,0:34:70:0,70,1125 0/0:36,0:36:81:0,81,1215 0/0:37,0:37:87:0,87,1305 0/0:43,0:43:99:0,102,1530 0/0:43,0:43:96:0,96,1440 0/0:37,0:37:87:0,87,1305 0/0:38,0:38:81:0,81,1215 0/0:59,0:59:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:116,0:116:99:0,120,1800 0/0:145,0:145:99:0,120,1800 0/0:127,0:127:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:41,0:41:99:0,99,1485 0/0:65,0:65:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/1:64,69:133:99:2027,0,2174 0/0:78,0:78:99:0,120,1800 0/0:108,0:108:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:129,0:129:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:40,0:40:81:0,81,1395 0/0:34,0:34:66:0,66,990 0/0:28,0:28:66:0,66,990 0/0:107,0:107:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/0:68,0:68:99:0,120,1800 0/0:51,0:51:81:0,81,1215 0/0:76,0:76:99:0,120,1800 0/0:39,0:39:96:0,96,1440 0/0:45,0:45:99:0,105,1575 0/0:37,0:37:84:0,84,1260 0/0:44,0:44:99:0,120,1800 0/0:44,0:44:99:0,99,1485 0/1:49,43:92:99:1314,0,1643 0/0:46,0:46:99:0,108,1620 0/0:39,0:39:79:0,79,1440 0/0:32,0:32:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:51,0:51:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:46,0:46:99:0,108,1620 0/0:102,0:102:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:56,0:56:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:34,0:34:75:0,75,1125 0/0:47,0:47:99:0,108,1620 0/0:32,0:32:69:0,69,1035 0/0:64,0:64:99:0,120,1800 +20 13550127 rs11697393 C T 67656.80 PASS HWP=0.6167;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.38;AN=200;InbreedingCoeff=0.0223;AF=0.073;GQ_STDDEV=164.08;FS=0.0;DP=25712;GQ_MEAN=124.54;POSITIVE_TRAIN_SITE;VQSLOD=5.65;ClippingRankSum=-0.023;BaseQRankSum=-3.093;MLEAF=0.073;MLEAC=127;MQ=60.0;QD=13.57;DB;MQRankSum=-0.037;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:60:0,60,900 0/0:38,0:38:54:0,54,810 0/0:22,0:22:63:0,63,862 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,813 0/0:30,0:30:78:0,78,1170 0/0:36,0:36:42:0,42,630 0/0:23,0:23:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:43,0:43:56:0,56,1585 0/0:25,0:25:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,839 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:66:0,66,886 0/0:23,0:23:63:0,63,945 0/0:30,0:30:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:39,0:39:99:0,105,1575 0/0:43,0:43:87:0,87,1305 0/0:31,0:31:70:0,70,1260 0/0:23,0:23:60:0,60,900 0/0:52,0:52:99:0,120,1800 0/0:54,0:54:99:0,114,1710 0/0:49,0:49:99:0,120,1800 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:62:0,62,1094 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,838 0/0:27,0:27:66:0,66,1033 0/0:37,0:37:81:0,81,1215 0/0:42,0:42:96:0,96,1440 0/0:26,0:26:60:0,60,900 0/0:46,0:46:99:0,114,1710 0/0:41,0:41:87:0,87,1305 0/0:47,0:47:99:0,120,1800 0/0:27,0:27:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,714 0/0:25,0:25:60:0,60,900 0/0:27,0:27:72:0,72,1080 0/0:28,0:28:75:0,75,1125 0/0:30,0:30:75:0,75,1125 0/0:36,0:36:71:0,71,1215 0/0:33,0:33:75:0,75,1125 0/0:36,0:36:90:0,90,1350 0/0:23,0:23:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:45,0:45:99:0,99,1485 0/0:24,0:24:60:0,60,900 0/1:12,19:31:99:599,0,350 0/0:28,0:28:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:11,0:11:27:0,27,405 0/0:50,0:50:99:0,120,1800 0/0:24,0:24:60:0,60,900 0/0:42,0:42:99:0,105,1575 0/0:26,0:26:60:0,60,900 0/0:46,0:46:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,759 0/0:29,0:29:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:44,0:44:99:0,108,1620 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:38,0:38:87:0,87,1305 0/0:22,0:22:60:0,60,900 0/1:13,17:30:99:488,0,447 0/0:31,0:31:75:0,75,1125 0/0:21,0:21:60:0,60,782 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:72:0,72,1080 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 +20 13550131 . A AT 2085.93 PASS HWP=1.0;AC=5;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.046;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=34.46;FS=2.042;DP=24658;GQ_MEAN=70.11;VQSLOD=2.96;ClippingRankSum=-0.751;BaseQRankSum=0.298;MLEAF=0.002874;MLEAC=5;MQ=60.0;QD=9.44;MQRankSum=0.38;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:20,23:43:99:504,0,473 0/1:18,19:37:99:438,0,431 0/0:22,0:22:63:0,63,862 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,813 0/0:30,0:30:78:0,78,1170 0/1:18,16:34:99:361,0,438 0/1:26,14:40:99:286,0,626 0/0:28,0:28:63:0,63,945 0/0:37,0:37:41:0,41,1211 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,839 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:66:0,66,886 0/0:23,0:23:63:0,63,945 0/0:30,0:30:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:39,0:39:99:0,105,1575 0/1:37,30:67:99:644,0,897 0/0:31,0:31:70:0,70,1260 0/0:23,0:23:60:0,60,900 0/0:52,0:52:99:0,120,1800 0/0:54,0:54:99:0,114,1710 0/0:49,0:49:99:0,120,1800 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:62:0,62,1094 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,838 0/0:42,0:42:45:0,45,1364 0/0:37,0:37:81:0,81,1215 0/0:42,0:42:96:0,96,1440 0/0:26,0:26:60:0,60,900 0/0:46,0:46:99:0,114,1710 0/0:41,0:41:87:0,87,1305 0/0:47,0:47:99:0,120,1800 0/0:27,0:27:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,714 0/0:25,0:25:60:0,60,900 0/0:27,0:27:72:0,72,1080 0/0:28,0:28:75:0,75,1125 0/0:30,0:30:75:0,75,1125 0/0:36,0:36:71:0,71,1215 0/0:33,0:33:75:0,75,1125 0/0:36,0:36:90:0,90,1350 0/0:23,0:23:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:45,0:45:99:0,99,1485 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:11,0:11:27:0,27,405 0/0:50,0:50:99:0,120,1800 0/0:24,0:24:60:0,60,900 0/0:42,0:42:99:0,105,1575 0/0:26,0:26:60:0,60,900 0/0:46,0:46:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,759 0/0:29,0:29:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:44,0:44:99:0,108,1620 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:38,0:38:87:0,87,1305 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:75:0,75,1125 0/0:21,0:21:60:0,60,782 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:72:0,72,1080 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,945 +20 13561495 rs113913531 A G 5615.93 PASS HWP=1.0;AC=2;culprit=MQRankSum;MQ0=0;ReadPosRankSum=0.516;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=76.4;FS=1.545;DP=55045;GQ_MEAN=74.69;POSITIVE_TRAIN_SITE;VQSLOD=2.88;ClippingRankSum=-0.391;BaseQRankSum=4.07;MLEAF=0.002874;MLEAC=5;MQ=59.05;QD=15.34;DB;MQRankSum=-0.365;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:56,0:56:99:0,120,1800 0/0:61,0:61:60:0,60,900 0/0:48,0:48:63:0,63,945 0/0:61,0:61:69:0,69,1035 0/0:66,0:66:69:0,69,1035 0/0:65,0:65:69:0,69,1035 0/0:55,0:55:63:0,63,945 0/0:50,0:50:60:0,60,900 0/0:62,0:62:69:0,69,1035 0/0:53,0:53:63:0,63,945 0/0:51,0:51:60:0,60,900 0/0:58,0:58:63:0,63,945 0/0:57,0:57:66:0,66,990 0/0:53,0:53:63:0,63,945 0/0:23,0:23:54:0,54,810 0/0:43,0:43:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:40,0:40:66:0,66,990 0/0:33,0:33:69:0,69,1035 0/0:35,0:35:69:0,69,1035 0/0:36,0:36:69:0,69,1035 0/0:44,0:44:81:0,81,1215 0/0:35,0:35:66:0,66,990 0/0:97,0:97:63:0,63,945 0/0:93,0:93:60:0,60,900 0/0:67,0:67:60:0,60,900 0/0:67,0:67:99:0,99,1485 0/0:58,0:58:60:0,60,900 0/0:102,0:102:99:0,108,1620 0/0:87,0:87:90:0,90,1350 0/0:82,0:82:63:0,63,945 0/0:68,0:68:63:0,63,945 0/0:78,0:78:63:0,63,945 0/0:117,0:117:99:0,111,1665 0/0:98,0:98:90:0,90,1350 0/0:46,0:46:84:0,84,1260 0/0:75,0:75:69:0,69,1035 0/0:47,0:47:60:0,60,900 0/0:58,0:58:93:0,93,1395 0/0:80,0:80:75:0,75,1125 0/0:52,0:52:69:0,69,1035 0/0:54,0:54:63:0,63,945 0/0:65,0:65:66:0,66,990 0/0:58,0:58:66:0,66,990 0/1:43,49:92:99:1555,0,1272 0/0:63,0:63:63:0,63,945 0/0:66,0:66:63:0,63,945 0/1:49,41:90:99:1321,0,1535 0/0:57,0:57:63:0,63,945 0/0:67,0:67:60:0,60,900 0/0:62,0:62:60:0,60,900 0/0:58,0:58:60:0,60,900 0/0:47,0:47:60:0,60,900 0/0:50,0:50:60:0,60,900 0/0:62,0:62:66:0,66,990 0/0:61,0:61:63:0,63,945 0/0:72,0:72:63:0,63,945 0/0:69,0:69:66:0,66,990 0/0:77,0:77:81:0,81,1215 0/0:51,0:51:60:0,60,900 0/0:59,0:59:69:0,69,1035 0/0:66,0:66:78:0,78,1170 0/0:112,0:112:72:0,72,1080 0/0:56,0:56:63:0,63,945 0/0:59,0:59:87:0,87,1305 0/0:28,0:28:44:0,44,949 0/0:34,0:34:66:0,66,990 0/0:46,0:46:66:0,66,990 0/0:59,0:59:63:0,63,945 0/0:44,0:44:63:0,63,945 0/0:70,0:70:99:0,102,1530 0/0:56,0:56:75:0,75,1125 0/0:79,0:79:87:0,87,1305 0/0:43,0:43:66:0,66,990 0/0:52,0:52:75:0,75,1125 0/0:32,0:32:69:0,69,1035 0/0:59,0:59:78:0,78,1170 0/0:57,0:57:63:0,63,945 0/0:50,0:50:60:0,60,900 0/0:44,0:44:66:0,66,990 0/0:43,0:43:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:40,0:40:63:0,63,945 0/0:44,0:44:60:0,60,900 0/0:53,0:53:63:0,63,945 0/0:74,0:74:66:0,66,990 0/0:57,0:57:63:0,63,945 0/0:58,0:58:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:106,0:106:72:0,72,1080 0/0:78,0:78:90:0,90,1350 0/0:66,0:66:60:0,60,900 0/0:47,0:47:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:73,0:73:93:0,93,1395 0/0:63,0:63:93:0,93,1395 0/0:33,0:33:63:0,63,945 0/0:46,0:46:69:0,69,1035 0/0:36,0:36:63:0,63,945 0/0:55,0:55:66:0,66,990 +20 13561632 . T TA 89057.40 PASS HWP=0.0;AC=29;culprit=QD;MQ0=0;ReadPosRankSum=-0.243;AN=200;InbreedingCoeff=0.1878;AF=0.115;GQ_STDDEV=65.36;FS=0.0;DP=50115;GQ_MEAN=73.88;POSITIVE_TRAIN_SITE;VQSLOD=4.57;ClippingRankSum=0.131;BaseQRankSum=0.34;MLEAF=0.109;MLEAC=190;MQ=59.62;QD=4.59;DB;MQRankSum=0.208;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/1:14,4:25:48:48,0,315 0/0:18,0:28:57:0,57,448 0/0:12,0:17:40:0,40,381 0/1:14,2:16:22:22,0,248 0/0:19,8:40:0:0,0,478 0/0:17,6:32:0:0,0,413 0/0:11,5:25:0:0,0,273 0/0:19,0:26:56:0,56,443 0/1:6,6:22:99:194,0,121 0/0:13,2:25:32:0,32,477 0/1:11,5:20:54:54,0,255 0/0:15,0:22:44:0,44,344 0/1:13,9:29:96:96,0,324 0/0:11,3:27:11:0,11,330 0/0:1,0:10:3:0,3,25 0/0:3,0:6:12:0,12,95 0/0:17,0:21:51:0,51,400 0/0:16,0:21:47:0,47,358 0/0:10,0:15:29:0,29,205 0/1:4,8:12:58:147,0,58 0/1:3,4:10:23:136,0,23 0/0:12,0:28:35:0,35,276 0/1:8,7:20:77:77,0,188 0/1:6,6:12:56:73,0,56 0/0:49,0:49:18:0,18,270 0/1:7,10:24:99:107,0,171 0/0:6,3:22:0:0,0,138 0/0:24,0:28:71:0,71,548 0/1:22,9:48:99:188,0,536 0/1:25,11:47:65:65,0,576 0/0:7,8:30:0:0,0,126 0/0:5,4:17:0:0,0,59 0/0:12,0:32:36:0,36,280 0/0:23,11:54:0:0,0,605 0/0:34,0:49:99:0,101,811 0/0:34,0:34:27:0,27,405 0/0:1,0:23:0:0,0,9 0/0:3,0:16:0:0,0,31 0/0:2,0:12:0:0,0,4 0/0:24,7:44:0:0,0,591 0/0:7,3:20:0:0,0,216 0/0:13,4:26:0:0,0,332 0/0:6,0:21:17:0,17,147 0/0:8,0:25:24:0,24,196 0/1:14,9:30:99:104,0,328 0/0:14,7:34:0:0,0,276 0/1:12,10:27:99:105,0,262 0/0:22,3:38:42:0,42,597 0/0:6,5:20:0:0,0,126 0/1:3,9:24:0:425,0,0 0/1:20,2:22:20:20,0,338 0/0:15,0:25:45:0,45,353 0/0:7,0:17:21:0,21,172 0/0:8,0:24:0:0,0,111 0/0:17,0:25:57:0,57,552 0/0:15,4:28:0:0,0,368 0/0:12,3:20:0:0,0,156 0/0:3,0:9:0:0,0,54 0/1:4,7:19:9:388,0,9 0/1:2,5:12:0:259,0,0 0/0:5,0:22:15:0,15,123 0/1:2,5:16:0:458,0,0 0/0:4,4:25:0:0,68,0 0/0:14,4:23:0:0,0,327 0/0:4,0:22:12:0,12,98 0/0:8,3:14:0:0,0,207 0/0:10,0:18:5:0,5,201 0/0:7,0:14:24:0,24,226 0/0:4,0:14:17:0,17,148 0/0:7,0:11:24:0,24,226 0/0:25,7:48:23:0,23,663 0/1:1,4:9:0:447,0,0 0/0:24,10:50:0:0,0,598 0/1:8,4:16:45:45,0,189 0/1:1,5:14:61:78,0,61 0/0:11,0:17:32:0,32,246 0/0:4,0:18:12:0,12,98 0/0:13,0:23:39:0,39,285 0/0:13,5:30:0:0,0,338 0/0:11,4:22:0:0,0,148 0/0:3,0:13:9:0,9,59 0/0:21,0:21:0:0,0,297 0/1:2,2:12:13:13,0,97 0/0:14,0:26:42:0,42,326 0/0:9,5:30:0:0,0,185 0/1:9,9:25:91:415,0,91 0/0:0,0:6:7:0,7,13 0/0:37,0:37:0:0,0,658 0/1:4,7:11:50:107,0,50 0/0:7,5:27:0:0,0,46 0/1:2,2:13:4:179,0,4 0/1:3,6:20:81:81,0,124 0/1:5,7:16:86:86,0,114 0/0:1,0:11:6:0,6,41 0/0:5,0:11:22:0,22,143 0/0:3,0:8:16:0,16,66 0/0:9,0:13:27:0,27,201 0/0:38,0:38:0:0,0,510 0/1:6,7:13:92:125,0,92 0/0:8,0:17:29:0,29,269 +20 13561632 . T TAA 89057.40 PASS HWP=0.0;AC=42;culprit=QD;MQ0=0;ReadPosRankSum=-0.243;AN=200;InbreedingCoeff=0.1878;AF=0.132;GQ_STDDEV=65.36;FS=0.0;DP=50115;GQ_MEAN=73.88;POSITIVE_TRAIN_SITE;VQSLOD=4.57;ClippingRankSum=0.131;BaseQRankSum=0.34;MLEAF=0.131;MLEAC=227;MQ=59.62;QD=4.59;DB;MQRankSum=0.208;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:14,1:25:22:0,22,601 0/0:18,0:28:57:0,57,448 0/1:12,5:17:99:158,0,313 0/0:14,0:16:44:0,44,304 0/0:19,0:40:57:0,57,459 0/0:17,0:32:51:0,51,411 0/0:11,0:25:8:0,8,217 0/0:19,0:26:56:0,56,443 0/0:6,5:22:0:0,0,248 0/0:13,0:25:41:0,41,359 0/0:11,0:20:34:0,34,269 0/0:15,0:22:44:0,44,344 0/0:13,0:29:39:0,39,317 0/0:11,0:27:33:0,33,263 0/1:1,6:10:65:139,0,65 0/1:3,3:6:64:149,0,64 0/0:17,0:21:51:0,51,400 0/0:16,0:21:47:0,47,358 0/0:10,0:15:29:0,29,205 0/0:4,0:12:14:0,14,100 0/1:3,3:10:64:138,0,64 0/1:12,11:28:99:185,0,403 0/0:8,0:20:24:0,24,183 0/0:6,0:12:21:0,21,94 0/0:49,0:49:18:0,18,270 0/0:7,0:24:21:0,21,166 0/0:6,0:22:0:0,0,97 0/0:24,0:28:71:0,71,548 0/0:22,0:48:0:0,0,426 0/0:25,0:47:44:0,44,549 0/1:7,9:30:99:319,0,250 0/1:5,4:17:99:294,0,106 0/1:12,15:32:99:291,0,388 0/0:23,0:54:44:0,44,521 0/0:34,0:49:99:0,101,811 0/0:34,0:34:27:0,27,405 0/1:1,10:23:99:200,0,184 0/1:3,5:16:99:256,0,145 0/1:2,6:12:1:485,0,1 0/0:24,0:44:72:0,72,583 0/0:7,0:20:21:0,21,170 0/0:13,0:26:39:0,39,316 0/1:6,8:21:99:162,0,288 0/1:8,12:25:99:198,0,300 0/0:14,0:30:28:0,28,325 0/0:14,0:34:0:0,0,257 0/0:12,0:27:36:0,36,292 0/0:22,0:38:66:0,66,535 0/1:6,6:20:99:156,0,211 0/1:3,12:24:18:554,0,18 0/0:20,0:22:60:0,60,409 0/0:15,3:25:0:0,0,568 0/1:7,6:17:83:83,0,254 0/1:8,6:24:99:434,0,268 0/1:17,8:25:99:228,0,455 0/0:15,0:28:45:0,45,365 0/0:12,0:20:0:0,0,166 0/1:3,4:9:52:380,0,52 0/1:4,5:19:67:467,0,67 0/1:2,5:12:26:299,0,26 0/1:5,9:22:99:183,0,269 0/0:2,0:16:0:0,42,0 0/1:4,8:25:0:1246,0,0 0/1:14,5:23:99:281,0,383 0/1:4,9:22:99:168,0,254 0/0:8,0:14:24:0,24,195 0/0:10,0:18:5:0,5,201 0/1:7,7:14:99:364,0,157 0/1:4,10:14:67:499,0,67 0/1:7,4:11:99:110,0,184 0/0:25,0:48:75:0,75,604 0/1:1,4:9:0:533,0,0 0/0:24,0:50:31:0,31,519 0/0:8,0:16:23:0,23,193 0/0:1,0:14:0:0,0,19 0/0:11,0:17:32:0,32,246 0/1:4,11:18:99:251,0,148 0/0:13,0:23:39:0,39,285 0/0:13,0:30:15:0,15,268 0/1:11,7:22:99:246,0,266 0/1:3,6:13:99:117,0,121 0/0:21,0:21:0:0,0,297 0/0:2,0:12:6:0,6,48 0/0:14,0:26:42:0,42,326 0/1:9,10:30:99:321,0,339 0/1:9,4:25:99:435,0,176 1/1:0,6:6:35:351,35,0 0/0:37,0:37:0:0,0,658 0/0:4,0:11:13:0,13,86 0/1:7,15:27:99:719,0,123 0/1:2,9:13:31:305,0,31 0/0:3,0:20:9:0,9,73 0/0:5,0:16:15:0,15,118 1/1:1,10:11:7:322,7,0 0/1:5,6:11:85:254,0,85 0/0:3,0:8:16:0,16,66 0/0:9,0:13:27:0,27,201 0/0:38,0:38:0:0,0,510 0/0:6,0:13:19:0,19,134 0/1:8,9:17:99:289,0,204 +20 13561632 . T TAAA 89057.40 PASS HWP=0.0;AC=6;culprit=QD;MQ0=0;ReadPosRankSum=-0.243;AN=200;InbreedingCoeff=0.1878;AF=0.024;GQ_STDDEV=65.36;FS=0.0;DP=50115;GQ_MEAN=73.88;POSITIVE_TRAIN_SITE;VQSLOD=4.57;ClippingRankSum=0.131;BaseQRankSum=0.34;MLEAF=0.022;MLEAC=38;MQ=59.62;QD=4.59;DB;MQRankSum=0.208;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:14,0:25:13:0,13,296 0/0:18,0:28:57:0,57,448 0/0:12,0:17:40:0,40,381 0/0:14,0:16:44:0,44,304 0/0:19,0:40:57:0,57,459 0/0:17,0:32:51:0,51,411 0/0:11,0:25:8:0,8,217 0/0:19,0:26:56:0,56,443 0/0:6,0:22:0:0,0,99 0/0:13,0:25:41:0,41,359 0/0:11,0:20:34:0,34,269 0/0:15,0:22:44:0,44,344 0/0:13,0:29:39:0,39,317 0/0:11,0:27:33:0,33,263 0/0:1,0:10:3:0,3,25 0/0:3,0:6:12:0,12,95 0/0:17,0:21:51:0,51,400 0/0:16,0:21:47:0,47,358 0/0:10,0:15:29:0,29,205 0/0:4,0:12:14:0,14,100 0/0:3,0:10:0:0,0,35 0/0:12,0:28:35:0,35,276 0/0:8,0:20:24:0,24,183 0/0:6,0:12:21:0,21,94 0/0:49,0:49:18:0,18,270 0/0:7,0:24:21:0,21,166 0/1:6,7:22:99:212,0,372 0/0:24,0:28:71:0,71,548 0/0:22,0:48:0:0,0,426 0/0:25,0:47:44:0,44,549 0/0:7,0:30:0:0,0,86 0/0:5,4:17:0:0,0,228 0/0:12,0:32:36:0,36,280 0/0:23,0:54:44:0,44,521 0/0:34,0:49:99:0,101,811 0/0:34,0:34:27:0,27,405 0/0:1,0:23:0:0,0,9 0/0:3,3:16:0:0,0,242 0/1:2,4:12:58:453,0,58 0/0:24,0:44:72:0,72,583 0/0:7,0:20:21:0,21,170 0/0:13,0:26:39:0,39,316 0/0:6,0:21:17:0,17,147 0/0:8,0:25:24:0,24,196 0/0:14,0:30:28:0,28,325 0/1:14,8:34:99:291,0,699 0/0:12,0:27:36:0,36,292 0/0:22,0:38:66:0,66,535 0/0:6,0:20:0:0,0,109 0/0:3,0:24:0:0,7,0 0/0:20,0:22:60:0,60,409 0/0:15,0:25:45:0,45,353 0/0:7,0:17:21:0,21,172 0/0:8,5:24:0:0,0,419 0/0:17,0:25:57:0,57,552 0/0:15,0:28:45:0,45,365 0/1:12,5:20:99:405,0,426 0/0:3,2:9:0:0,0,94 0/0:4,3:19:0:0,0,150 0/0:2,0:12:0:0,0,9 0/0:5,0:22:15:0,15,123 0/1:2,9:16:31:636,0,31 0/0:4,0:25:0:0,71,0 0/0:14,0:23:0:0,0,253 0/0:4,0:22:12:0,12,98 0/0:8,0:14:24:0,24,195 0/0:10,0:18:5:0,5,201 0/0:7,0:14:24:0,24,226 0/0:4,0:14:17:0,17,148 0/0:7,0:11:24:0,24,226 0/0:25,0:48:75:0,75,604 0/0:1,0:9:0:0,52,0 0/0:24,0:50:31:0,31,519 0/0:8,0:16:23:0,23,193 0/0:1,0:14:0:0,0,19 0/0:11,0:17:32:0,32,246 0/0:4,0:18:12:0,12,98 0/0:13,0:23:39:0,39,285 0/0:13,0:30:15:0,15,268 0/0:11,0:22:0:0,0,160 0/0:3,0:13:9:0,9,59 0/0:21,0:21:0:0,0,297 0/0:2,0:12:6:0,6,48 0/0:14,0:26:42:0,42,326 0/0:9,0:30:0:0,0,152 0/0:9,3:25:0:0,0,316 0/0:0,0:6:7:0,7,13 0/0:37,0:37:0:0,0,658 0/0:4,0:11:13:0,13,86 0/0:7,0:27:0:0,0,60 0/0:2,0:13:0:0,0,12 0/0:3,0:20:9:0,9,73 0/0:5,0:16:15:0,15,118 0/0:1,0:11:6:0,6,41 0/0:5,0:11:22:0,22,143 0/1:3,5:8:17:268,0,17 0/0:9,0:13:27:0,27,201 0/0:38,0:38:0:0,0,510 0/0:6,0:13:19:0,19,134 0/0:8,0:17:29:0,29,269 +20 13561632 . T TAAAA 89057.40 PASS HWP=0.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=-0.243;AN=200;InbreedingCoeff=0.1878;AF=0.002877;GQ_STDDEV=65.36;FS=0.0;DP=50115;GQ_MEAN=73.88;POSITIVE_TRAIN_SITE;VQSLOD=4.57;ClippingRankSum=0.131;BaseQRankSum=0.34;MLEAF=0.002877;MLEAC=5;MQ=59.62;QD=4.59;DB;MQRankSum=0.208;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:14,0:25:13:0,13,296 0/0:18,0:28:57:0,57,448 0/0:12,0:17:40:0,40,381 0/0:14,0:16:44:0,44,304 0/0:19,0:40:57:0,57,459 0/0:17,0:32:51:0,51,411 0/0:11,0:25:8:0,8,217 0/0:19,0:26:56:0,56,443 0/0:6,0:22:0:0,0,99 0/0:13,0:25:41:0,41,359 0/0:11,0:20:34:0,34,269 0/0:15,0:22:44:0,44,344 0/0:13,0:29:39:0,39,317 0/0:11,0:27:33:0,33,263 0/0:1,0:10:3:0,3,25 0/0:3,0:6:12:0,12,95 0/0:17,0:21:51:0,51,400 0/0:16,0:21:47:0,47,358 0/0:10,0:15:29:0,29,205 0/0:4,0:12:14:0,14,100 0/0:3,0:10:0:0,0,35 0/0:12,0:28:35:0,35,276 0/0:8,0:20:24:0,24,183 0/0:6,0:12:21:0,21,94 0/0:49,0:49:18:0,18,270 0/0:7,0:24:21:0,21,166 0/0:6,0:22:0:0,0,97 0/0:24,0:28:71:0,71,548 0/0:22,0:48:0:0,0,426 0/0:25,0:47:44:0,44,549 0/0:7,0:30:0:0,0,86 0/0:5,0:17:0:0,0,68 0/0:12,0:32:36:0,36,280 0/0:23,0:54:44:0,44,521 0/0:34,0:49:99:0,101,811 0/0:34,0:34:27:0,27,405 0/0:1,0:23:0:0,0,9 0/0:3,0:16:0:0,0,31 0/0:2,0:12:0:0,0,4 0/0:24,0:44:72:0,72,583 0/0:7,0:20:21:0,21,170 0/0:13,0:26:39:0,39,316 0/0:6,0:21:17:0,17,147 0/0:8,0:25:24:0,24,196 0/0:14,0:30:28:0,28,325 0/0:14,0:34:0:0,0,257 0/0:12,0:27:36:0,36,292 0/0:22,0:38:66:0,66,535 0/0:6,0:20:0:0,0,109 0/0:3,0:24:0:0,7,0 0/0:20,0:22:60:0,60,409 0/0:15,0:25:45:0,45,353 0/0:7,0:17:21:0,21,172 0/0:8,0:24:0:0,0,111 0/0:17,0:25:57:0,57,552 0/0:15,0:28:45:0,45,365 0/0:12,0:20:0:0,0,166 0/0:3,0:9:0:0,0,54 0/0:4,0:19:0:0,0,23 0/0:2,0:12:0:0,0,9 0/0:5,0:22:15:0,15,123 0/0:2,0:16:0:0,42,0 0/1:4,9:25:99:1193,0,135 0/0:14,0:23:0:0,0,253 0/0:4,0:22:12:0,12,98 0/0:8,0:14:24:0,24,195 0/0:10,0:18:5:0,5,201 0/0:7,0:14:24:0,24,226 0/0:4,0:14:17:0,17,148 0/0:7,0:11:24:0,24,226 0/0:25,0:48:75:0,75,604 0/0:1,0:9:0:0,52,0 0/0:24,0:50:31:0,31,519 0/0:8,0:16:23:0,23,193 0/0:1,0:14:0:0,0,19 0/0:11,0:17:32:0,32,246 0/0:4,0:18:12:0,12,98 0/0:13,0:23:39:0,39,285 0/0:13,0:30:15:0,15,268 0/0:11,0:22:0:0,0,160 0/0:3,0:13:9:0,9,59 0/0:21,0:21:0:0,0,297 0/0:2,0:12:6:0,6,48 0/0:14,0:26:42:0,42,326 0/0:9,0:30:0:0,0,152 0/0:9,0:25:0:0,0,101 0/0:0,0:6:7:0,7,13 0/0:37,0:37:0:0,0,658 0/0:4,0:11:13:0,13,86 0/0:7,0:27:0:0,0,60 0/0:2,0:13:0:0,0,12 0/0:3,0:20:9:0,9,73 0/0:5,0:16:15:0,15,118 0/0:1,0:11:6:0,6,41 0/0:5,0:11:22:0,22,143 0/0:3,0:8:16:0,16,66 0/0:9,0:13:27:0,27,201 0/0:38,0:38:0:0,0,510 0/0:6,0:13:19:0,19,134 0/0:8,0:17:29:0,29,269 +20 13561632 . TA T 89057.40 PASS HWP=0.0;AC=38;culprit=QD;MQ0=0;ReadPosRankSum=-0.243;AN=200;InbreedingCoeff=0.1878;AF=0.227;GQ_STDDEV=65.36;FS=0.0;DP=50115;GQ_MEAN=73.88;POSITIVE_TRAIN_SITE;VQSLOD=4.57;ClippingRankSum=0.131;BaseQRankSum=0.34;MLEAF=0.227;MLEAC=394;MQ=59.62;QD=4.59;DB;MQRankSum=0.208;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:14,6:25:0:0,0,397 0/1:18,10:28:99:119,0,360 0/0:12,0:17:40:0,40,381 0/0:14,0:16:44:0,44,304 0/1:19,13:40:99:153,0,500 0/1:17,9:32:95:95,0,430 0/1:11,6:25:97:97,0,319 0/1:19,7:26:97:97,0,364 0/0:6,5:22:0:0,0,362 0/1:13,10:25:99:133,0,475 0/0:11,0:20:34:0,34,269 0/1:15,7:22:95:95,0,277 0/0:13,7:29:0:0,0,468 0/1:11,13:27:99:232,0,288 0/1:1,3:10:45:45,0,70 0/0:3,0:6:12:0,12,95 0/1:17,4:21:37:37,0,336 0/1:16,5:21:62:62,0,294 0/1:10,5:15:66:66,0,160 0/0:4,0:12:14:0,14,100 0/0:3,0:10:0:0,0,35 0/0:12,5:28:0:0,0,324 0/0:8,5:20:0:0,0,279 0/0:6,0:12:21:0,21,94 0/0:49,0:49:18:0,18,270 0/1:7,7:24:92:92,0,201 0/0:6,6:22:0:0,0,320 0/1:24,4:28:4:4,0,462 0/0:22,14:48:0:0,0,790 0/0:25,7:47:0:0,0,737 0/0:7,6:30:8:0,8,429 0/0:5,0:17:0:0,0,68 0/0:12,5:32:11:0,11,670 0/1:23,16:54:99:225,0,818 0/1:34,15:49:99:199,0,662 0/0:34,0:34:27:0,27,405 0/1:1,8:23:99:160,0,131 0/1:3,5:16:64:64,0,159 0/0:2,0:12:0:0,0,4 0/1:24,13:44:99:153,0,717 0/1:7,10:20:99:175,0,242 0/1:13,9:26:99:141,0,300 0/1:6,7:21:99:99,0,186 0/0:8,5:25:0:0,0,305 0/0:14,7:30:0:0,0,417 0/0:14,5:34:11:0,11,516 0/0:12,5:27:0:0,0,427 0/1:22,13:38:99:154,0,639 0/0:6,3:20:0:0,0,286 0/0:3,0:24:0:0,7,0 0/0:20,0:22:60:0,60,409 0/1:15,7:25:55:55,0,521 0/0:7,4:17:0:0,0,330 0/0:8,5:24:18:0,18,458 0/0:17,0:25:57:0,57,552 0/1:15,9:28:86:86,0,406 0/0:12,0:20:0:0,0,166 0/0:3,0:9:0:0,0,54 0/0:4,0:19:0:0,0,23 0/0:2,0:12:0:0,0,9 0/1:5,8:22:99:113,0,291 0/0:2,0:16:0:0,42,0 0/0:4,0:25:0:0,71,0 0/0:14,0:23:0:0,0,253 0/1:4,9:22:99:128,0,235 0/0:8,0:14:24:0,24,195 0/0:10,4:18:0:0,0,184 0/0:7,0:14:24:0,24,226 0/0:4,0:14:17:0,17,148 0/0:7,0:11:24:0,24,226 0/1:25,16:48:99:241,0,635 0/0:1,0:9:0:0,52,0 0/1:24,10:50:99:141,0,671 0/0:8,4:16:0:0,0,308 0/1:1,8:14:71:155,0,71 0/1:11,6:17:99:99,0,194 0/0:4,3:18:0:0,0,254 0/1:13,10:23:99:162,0,214 0/1:13,9:30:99:163,0,296 0/0:11,0:22:0:0,0,160 0/1:3,4:13:53:53,0,162 0/0:21,0:21:0:0,0,297 0/1:2,8:12:54:146,0,54 0/1:14,12:26:99:189,0,247 0/0:9,6:30:0:0,0,385 0/0:9,0:25:0:0,0,101 0/0:0,0:6:7:0,7,13 0/0:37,0:37:0:0,0,658 0/0:4,0:11:13:0,13,86 0/0:7,0:27:0:0,0,60 0/0:2,0:13:0:0,0,12 0/1:3,11:20:91:157,0,91 0/0:5,4:16:0:0,0,249 0/0:1,0:11:6:0,6,41 0/0:5,0:11:22:0,22,143 0/0:3,0:8:16:0,16,66 0/1:9,4:13:47:47,0,161 0/0:38,0:38:0:0,0,510 0/0:6,0:13:19:0,19,134 0/0:8,0:17:29:0,29,269 +20 13561632 . TAA T 89057.40 PASS HWP=0.0;AC=2;culprit=QD;MQ0=0;ReadPosRankSum=-0.243;AN=200;InbreedingCoeff=0.1878;AF=0.00748;GQ_STDDEV=65.36;FS=0.0;DP=50115;GQ_MEAN=73.88;POSITIVE_TRAIN_SITE;VQSLOD=4.57;ClippingRankSum=0.131;BaseQRankSum=0.34;MLEAF=0.003452;MLEAC=6;MQ=59.62;QD=4.59;DB;MQRankSum=0.208;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:14,0:25:13:0,13,296 0/0:18,0:28:57:0,57,448 0/0:12,0:17:40:0,40,381 0/0:14,0:16:44:0,44,304 0/0:19,0:40:57:0,57,459 0/0:17,0:32:51:0,51,411 0/0:11,3:25:0:0,0,582 0/0:19,0:26:56:0,56,443 0/0:6,0:22:0:0,0,99 0/0:13,0:25:41:0,41,359 0/0:11,4:20:0:0,0,677 0/0:15,0:22:44:0,44,344 0/0:13,0:29:39:0,39,317 0/0:11,0:27:33:0,33,263 0/0:1,0:10:3:0,3,25 0/0:3,0:6:12:0,12,95 0/0:17,0:21:51:0,51,400 0/0:16,0:21:47:0,47,358 0/0:10,0:15:29:0,29,205 0/0:4,0:12:14:0,14,100 0/0:3,0:10:0:0,0,35 0/0:12,0:28:35:0,35,276 0/0:8,0:20:24:0,24,183 0/0:6,0:12:21:0,21,94 0/0:49,0:49:18:0,18,270 0/0:7,0:24:21:0,21,166 0/0:6,0:22:0:0,0,97 0/0:24,0:28:71:0,71,548 0/0:22,3:48:75:0,75,1579 0/0:25,4:47:22:0,22,1392 0/0:7,0:30:0:0,0,86 0/0:5,0:17:0:0,0,68 0/0:12,0:32:36:0,36,280 0/0:23,4:54:68:0,68,1727 0/0:34,0:49:99:0,101,811 0/0:34,0:34:27:0,27,405 0/0:1,4:23:0:0,0,356 0/0:3,0:16:0:0,0,31 0/0:2,0:12:0:0,0,4 0/0:24,0:44:72:0,72,583 0/0:7,0:20:21:0,21,170 0/0:13,0:26:39:0,39,316 0/0:6,0:21:17:0,17,147 0/0:8,0:25:24:0,24,196 0/0:14,0:30:28:0,28,325 0/0:14,0:34:0:0,0,257 0/0:12,0:27:36:0,36,292 0/0:22,0:38:66:0,66,535 0/0:6,0:20:0:0,0,109 0/0:3,0:24:0:0,7,0 0/0:20,0:22:60:0,60,409 0/0:15,0:25:45:0,45,353 0/0:7,0:17:21:0,21,172 0/0:8,0:24:0:0,0,111 0/0:17,0:25:57:0,57,552 0/0:15,0:28:45:0,45,365 0/0:12,0:20:0:0,0,166 0/0:3,0:9:0:0,0,54 0/0:4,0:19:0:0,0,23 0/0:2,0:12:0:0,0,9 0/0:5,0:22:15:0,15,123 0/0:2,0:16:0:0,42,0 0/0:4,0:25:0:0,71,0 0/0:14,0:23:0:0,0,253 0/0:4,0:22:12:0,12,98 0/1:8,3:14:44:44,0,486 0/1:10,4:18:91:91,0,286 0/0:7,0:14:24:0,24,226 0/0:4,0:14:17:0,17,148 0/0:7,0:11:24:0,24,226 0/0:25,0:48:75:0,75,604 0/0:1,0:9:0:0,52,0 0/0:24,6:50:0:0,0,1243 0/0:8,0:16:23:0,23,193 0/0:1,0:14:0:0,0,19 0/0:11,0:17:32:0,32,246 0/0:4,0:18:12:0,12,98 0/0:13,0:23:39:0,39,285 0/0:13,3:30:0:0,0,547 0/0:11,0:22:0:0,0,160 0/0:3,0:13:9:0,9,59 0/0:21,0:21:0:0,0,297 0/0:2,0:12:6:0,6,48 0/0:14,0:26:42:0,42,326 0/0:9,0:30:0:0,0,152 0/0:9,0:25:0:0,0,101 0/0:0,0:6:7:0,7,13 0/0:37,0:37:0:0,0,658 0/0:4,0:11:13:0,13,86 0/0:7,0:27:0:0,0,60 0/0:2,0:13:0:0,0,12 0/0:3,0:20:9:0,9,73 0/0:5,0:16:15:0,15,118 0/0:1,0:11:6:0,6,41 0/0:5,0:11:22:0,22,143 0/0:3,0:8:16:0,16,66 0/0:9,0:13:27:0,27,201 0/0:38,0:38:0:0,0,510 0/0:6,0:13:19:0,19,134 0/0:8,0:17:29:0,29,269 +20 13567973 rs117248024 C A 6048.93 PASS HWP=1.0;AC=2;culprit=ReadPosRankSum;MQ0=0;ReadPosRankSum=-1.039;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=89.62;FS=1.85;DP=25659;GQ_MEAN=69.34;POSITIVE_TRAIN_SITE;VQSLOD=3.22;ClippingRankSum=-0.135;BaseQRankSum=-6.252;MLEAF=0.002874;MLEAC=5;MQ=59.53;QD=13.56;DB;MQRankSum=0.175;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:34,0:34:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:33,0:33:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:29,0:29:67:0,67,1051 0/0:28,0:28:63:0,63,945 0/0:31,0:31:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:50,0:50:63:0,63,945 0/0:36,0:36:72:0,72,1080 0/0:33,0:33:60:0,60,900 0/0:32,0:32:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:61:0,61,945 0/0:30,0:30:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:27,0:27:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:30,0:30:60:0,60,900 0/1:66,51:117:99:1593,0,2383 0/0:35,0:35:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:27,0:27:60:0,60,900 0/0:38,0:38:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:35,0:35:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:41,0:41:90:0,90,1440 0/0:30,0:30:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:25,0:25:63:0,63,945 0/0:24,0:24:60:0,60,900 0/1:43,46:89:99:1445,0,1581 0/0:28,0:28:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:25,0:25:60:0,60,900 +20 13604122 . C T 31.72 VQSRTrancheSNP99.60to99.80 HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.963;AN=200;InbreedingCoeff=-0.0018;AF=5.747E-4;GQ_STDDEV=17.87;FS=3.808;DP=18709;GQ_MEAN=54.34;VQSLOD=-3.776;ClippingRankSum=-0.674;BaseQRankSum=0.706;MLEAF=5.747E-4;MLEAC=1;MQ=35.66;QD=0.72;MQRankSum=-1.316;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,786 0/0:23,0:23:60:0,60,833 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,899 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,873 0/0:19,0:19:45:0,45,648 0/0:21,0:21:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,846 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:66:0,66,898 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:63:0,63,659 0/0:21,0:21:60:0,60,808 0/0:24,0:24:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:27,0:27:63:0,63,918 0/0:24,0:24:63:0,63,900 0/0:22,0:22:60:0,60,900 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:86:0,86,1350 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,703 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:66:0,66,953 0/0:20,0:20:60:0,60,773 0/0:15,0:15:33:0,33,495 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,748 0/0:24,0:24:60:0,60,827 0/0:21,0:21:60:0,60,855 0/0:23,0:23:60:0,60,900 0/1:37,7:44:82:82,0,1000 0/0:33,0:33:75:0,75,1125 0/0:29,0:29:69:0,69,1035 0/0:21,0:21:60:0,60,779 0/0:22,0:22:43:0,43,705 0/0:14,0:14:33:0,33,495 0/0:23,0:23:60:0,60,857 0/0:21,0:21:60:0,60,883 0/0:24,0:24:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:30,0:30:40:0,40,947 0/0:25,0:25:60:0,60,900 0/0:30,0:30:81:0,81,1215 0/0:10,0:10:24:0,24,360 0/0:23,0:23:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:29,0:29:69:0,69,1035 0/0:10,0:10:24:0,24,360 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:26,0:26:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:13,0:13:30:0,30,450 0/0:7,0:7:21:0,21,285 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:19,0:19:36:0,36,540 0/0:25,0:25:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:8,0:8:21:0,21,315 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,780 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,868 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,848 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,796 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,870 0/0:14,0:14:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:20,0:20:60:0,60,743 0/0:20,0:20:51:0,51,765 0/0:17,0:17:36:0,36,540 0/0:14,0:14:33:0,33,495 0/0:24,0:24:60:0,60,900 +20 13605903 rs2070307 A T 803205.00 PASS NEGATIVE_TRAIN_SITE;HWP=0.0;AC=59;culprit=MQRankSum;MQ0=0;ReadPosRankSum=0.228;AN=200;InbreedingCoeff=0.1614;AF=0.396;GQ_STDDEV=496.16;FS=0.71;DP=53721;GQ_MEAN=464.48;POSITIVE_TRAIN_SITE;VQSLOD=1.3;ClippingRankSum=-0.084;BaseQRankSum=-2.696;MLEAF=0.396;MLEAC=689;MQ=58.73;QD=19.34;DB;MQRankSum=-1.474;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:60:0,60,900 0/1:30,30:60:99:798,0,898 0/0:32,0:32:63:0,63,945 0/1:31,38:69:99:983,0,850 0/0:33,0:33:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:40,0:40:99:0,99,1485 0/1:27,24:51:99:667,0,790 0/0:30,0:30:60:0,60,900 0/1:21,33:54:99:914,0,596 0/0:35,0:35:87:0,87,1305 0/0:34,0:34:69:0,69,1035 0/1:36,33:69:99:980,0,1016 0/1:33,26:59:99:708,0,896 0/1:34,29:63:99:807,0,964 0/1:46,40:86:99:1099,0,1362 1/1:0,58:58:99:2016,174,0 0/1:35,51:86:99:1455,0,909 0/1:36,31:67:99:824,0,1017 1/1:0,93:93:99:3168,279,0 0/1:51,31:82:99:835,0,1501 1/1:0,85:85:99:2911,255,0 0/0:31,0:31:66:0,66,990 0/1:89,88:177:99:2644,0,2427 0/0:31,0:31:60:0,60,900 0/1:47,43:90:99:1181,0,1429 0/1:37,69:106:99:1914,0,1056 0/0:41,0:41:93:0,93,1395 0/0:34,0:34:69:0,69,1035 0/1:43,32:75:99:794,0,1206 0/0:34,0:34:81:0,81,1215 1/1:1,68:69:99:2324,167,0 1/1:0,146:146:99:4936,439,0 0/1:80,77:157:99:2178,0,2351 0/0:72,0:72:99:0,120,1800 1/1:0,80:80:99:2475,240,0 0/1:55,42:97:99:1070,0,1606 0/1:51,34:85:99:965,0,1499 0/0:33,0:33:81:0,81,1215 0/1:50,38:88:99:1083,0,1544 0/0:25,0:25:60:0,60,900 0/1:21,31:52:99:867,0,651 0/1:31,30:61:99:878,0,937 0/0:37,0:37:72:0,72,1080 0/1:34,42:76:99:1222,0,1025 1/1:0,98:98:99:3359,295,0 0/0:47,0:47:99:0,105,1575 0/1:51,42:93:99:1112,0,1595 0/1:56,44:100:99:1169,0,1844 0/0:52,0:52:99:0,114,1710 0/1:43,34:77:99:930,0,1332 0/0:45,0:45:99:0,108,1620 0/1:35,29:64:99:784,0,1056 0/0:35,0:35:72:0,72,1080 0/1:74,52:126:99:1412,0,2197 0/0:36,0:36:84:0,84,1260 0/1:49,33:82:99:951,0,1547 0/0:58,0:58:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/1:65,55:120:99:1602,0,1957 0/0:34,0:34:84:0,84,1260 0/0:31,0:31:75:0,75,1125 0/1:72,60:132:99:1617,0,2215 0/0:46,0:46:99:0,111,1665 0/1:30,23:53:99:573,0,921 0/0:34,0:34:64:0,64,1170 0/0:25,0:25:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:64,0:64:99:0,120,1800 0/1:21,19:40:99:525,0,674 0/0:60,0:60:99:0,120,1800 0/0:31,0:31:60:0,60,900 0/1:88,72:160:99:1889,0,2441 0/1:52,37:89:99:950,0,1573 0/0:35,0:35:78:0,78,1170 0/0:23,0:23:60:0,60,900 0/0:35,0:35:78:0,78,1170 0/1:41,34:75:99:924,0,1274 1/1:0,78:78:99:2721,235,0 0/0:32,0:32:72:0,72,1080 0/1:30,22:52:99:583,0,904 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:43,0:43:90:0,90,1350 0/1:47,45:92:99:1280,0,1468 0/0:65,0:65:99:0,120,1800 0/0:23,0:23:60:0,60,900 0/0:34,0:34:63:0,63,945 0/1:52,31:83:99:894,0,1490 0/0:61,0:61:99:0,120,1800 0/0:42,0:42:63:0,63,945 0/1:36,53:89:99:1444,0,1001 0/1:48,28:76:99:748,0,1561 0/0:28,0:28:66:0,66,990 0/1:41,47:88:99:1249,0,1141 0/0:24,0:24:60:0,60,900 0/1:26,31:57:99:871,0,774 0/0:28,0:28:60:0,60,900 0/0:29,0:29:60:0,60,900 0/1:49,40:89:99:1060,0,1520 +20 13610657 . A C 583.67 VQSRTrancheSNP99.95to100.00 HWP=1.0;AC=3;culprit=FS;MQ0=0;ReadPosRankSum=-1.069;AN=200;InbreedingCoeff=-0.0128;AF=0.005172;GQ_STDDEV=27.1;FS=158.866;DP=36168;GQ_MEAN=74.98;VQSLOD=-211.0;ClippingRankSum=1.9;BaseQRankSum=-6.039;MLEAF=0.005172;MLEAC=9;MQ=59.54;QD=0.89;MQRankSum=-0.204;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:44,0:44:84:0,84,1260 0/0:33,0:33:72:0,72,1080 0/0:36,0:36:75:0,75,1125 0/0:38,0:38:87:0,87,1305 0/0:32,0:32:69:0,69,1035 0/0:42,0:42:84:0,84,1260 0/0:40,0:40:90:0,90,1350 0/0:26,0:26:69:0,69,1035 0/0:44,0:44:99:0,105,1575 0/0:26,0:26:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:34,0:34:65:0,65,1152 0/0:41,0:41:99:0,99,1485 0/0:38,0:38:90:0,90,1350 0/0:30,0:30:72:0,72,1080 0/0:32,0:32:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:35,0:35:78:0,78,1170 0/0:42,0:42:84:0,84,1260 0/0:37,0:37:75:0,75,1125 0/0:35,0:35:78:0,78,1170 0/0:46,0:46:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:46,0:46:99:0,106,1665 0/0:72,0:72:24:0,24,1882 0/0:81,0:81:0:0,0,1763 0/0:44,0:44:90:0,90,1350 0/0:56,0:56:99:0,120,1800 0/0:38,0:38:84:0,84,1260 0/0:29,0:29:63:0,63,945 0/0:57,0:57:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:59,0:59:99:0,117,1755 0/0:28,0:28:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:41,0:41:96:0,96,1440 0/0:41,0:41:93:0,93,1395 0/0:63,0:63:99:0,120,1800 0/0:46,0:46:0:0,0,1042 0/0:37,0:37:84:0,84,1260 0/0:58,0:58:0:0,0,1406 0/0:33,0:33:75:0,75,1125 0/0:45,0:45:99:0,106,1632 0/0:83,0:83:0:0,0,2018 0/0:51,0:51:99:0,120,1800 0/0:77,0:77:54:0,54,1904 0/0:48,0:48:99:0,108,1620 0/0:61,0:61:99:0,108,1620 0/0:49,0:49:62:0,62,1800 0/1:49,28:77:99:124,0,1216 0/0:58,0:58:54:0,54,1588 0/0:59,0:59:34:0,34,1494 0/0:28,0:28:66:0,66,990 0/0:37,0:37:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/1:55,25:80:94:94,0,1467 0/0:47,0:47:99:0,102,1530 0/0:61,0:61:35:0,35,1588 0/0:45,0:45:81:0,81,1215 0/0:119,0:119:50:0,50,2988 0/0:79,0:79:0:0,0,1604 0/0:40,0:40:87:0,87,1305 0/0:38,0:38:72:0,72,1080 0/0:61,0:61:0:0,0,1471 0/0:23,0:23:60:0,60,900 0/0:69,0:69:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:41,0:41:81:0,81,1215 0/0:32,0:32:66:0,66,990 0/0:34,0:34:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:46,0:46:99:0,102,1396 0/0:28,0:28:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:31,0:31:78:0,78,1170 0/0:31,0:31:69:0,69,1035 0/0:31,0:31:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:34,0:34:69:0,69,1035 0/0:37,0:37:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:31,0:31:67:0,67,1035 0/0:48,0:48:99:0,108,1620 0/0:42,0:42:84:0,84,1260 0/0:32,0:32:66:0,66,990 0/0:59,0:59:26:0,26,1482 0/0:48,0:48:37:0,37,1322 0/0:32,0:32:60:0,60,900 0/0:36,0:36:66:0,66,990 0/1:36,19:55:72:72,0,947 0/0:33,0:33:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:54,0:54:1:0,1,1294 +20 13695498 rs6079146 G A 71539.40 PASS HWP=0.9944;AC=25;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.491;AN=200;InbreedingCoeff=-0.0214;AF=0.121;GQ_STDDEV=140.65;FS=0.0;DP=16029;GQ_MEAN=98.36;POSITIVE_TRAIN_SITE;VQSLOD=6.49;ClippingRankSum=-0.296;BaseQRankSum=-2.383;MLEAF=0.123;MLEAC=214;MQ=60.0;QD=16.04;DB;MQRankSum=0.161;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:9,0:9:24:0,24,324 0/0:14,0:14:26:0,26,515 0/0:7,0:7:21:0,21,253 0/1:6,6:12:99:195,0,170 0/0:12,0:12:33:0,33,455 0/1:5,5:10:99:159,0,170 0/0:9,0:9:24:0,24,360 0/0:15,0:15:27:0,27,490 0/0:24,0:24:60:0,60,900 0/1:10,6:16:99:181,0,328 0/0:10,0:10:30:0,30,395 0/1:5,6:11:99:196,0,142 0/0:14,0:14:36:0,36,540 0/0:9,0:9:24:0,24,360 0/1:25,15:40:99:417,0,799 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:44:0,44,965 0/1:10,18:28:99:575,0,321 0/0:28,0:28:75:0,75,1087 0/0:23,0:23:66:0,66,990 0/0:23,0:23:60:0,60,900 0/1:16,14:30:99:394,0,515 0/1:17,11:28:99:332,0,613 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:15,22:37:99:731,0,501 0/0:41,0:41:72:0,72,1080 0/1:7,10:17:99:296,0,247 0/0:15,0:15:42:0,42,630 0/0:23,0:23:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:31,0:31:60:0,60,900 0/1:15,18:33:99:568,0,577 0/0:35,0:35:75:0,75,1305 0/0:10,0:10:30:0,30,370 0/1:4,6:10:99:181,0,148 0/0:25,0:25:60:0,60,900 0/0:32,0:32:87:0,87,1305 0/0:38,0:38:96:0,96,1440 0/1:16,15:31:99:512,0,563 0/0:35,0:35:99:0,102,1530 0/0:26,0:26:69:0,69,1035 0/0:20,0:20:60:0,60,767 0/0:26,0:26:69:0,69,980 0/1:20,26:46:99:865,0,669 0/0:40,0:40:98:0,98,1485 0/1:27,29:56:99:982,0,918 0/1:15,14:29:99:486,0,561 0/0:31,0:31:74:0,74,1196 0/0:24,0:24:60:0,60,900 0/0:38,0:38:99:0,105,1494 0/0:23,0:23:60:0,60,900 0/1:9,7:16:99:235,0,346 0/0:22,0:22:60:0,60,900 0/0:27,0:27:75:0,75,940 0/0:39,0:39:60:0,60,900 0/0:34,0:34:80:0,80,1305 0/1:27,18:45:99:526,0,868 0/1:22,26:48:99:879,0,823 0/0:29,0:29:78:0,78,1170 0/1:23,17:40:99:547,0,799 0/0:21,0:21:60:0,60,900 0/0:27,0:27:78:0,78,993 0/0:27,0:27:64:0,64,1123 0/0:21,0:21:30:0,30,692 0/1:5,6:11:99:166,0,193 0/0:7,0:7:21:0,21,280 0/0:33,0:33:75:0,75,1190 0/0:8,0:8:21:0,21,270 0/0:30,0:30:81:0,81,1215 0/0:20,0:20:60:0,60,740 0/0:23,0:23:63:0,63,897 0/0:8,0:8:21:0,21,280 0/0:9,0:9:24:0,24,360 0/0:7,0:7:21:0,21,247 0/1:9,8:17:99:271,0,344 0/1:9,8:17:99:275,0,290 0/0:12,0:12:27:0,27,413 0/0:21,0:21:60:0,60,900 0/0:15,0:15:39:0,39,585 0/1:7,8:15:99:274,0,229 0/0:15,0:15:36:0,36,540 0/1:9,13:22:99:430,0,320 0/0:21,0:21:60:0,60,883 0/0:21,0:21:60:0,60,849 0/0:7,0:7:21:0,21,261 0/0:7,0:7:21:0,21,215 0/0:29,0:29:84:0,84,1260 0/0:22,0:22:63:0,63,945 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,284 0/0:22,0:22:57:0,57,855 0/0:21,0:21:60:0,60,900 0/0:8,0:8:24:0,24,274 0/0:7,0:7:21:0,21,263 0/0:23,0:23:62:0,62,863 0/0:21,0:21:60:0,60,900 0/0:11,0:11:24:0,24,388 0/0:21,0:21:60:0,60,900 +20 13695607 rs34414644 T G 180354.00 PASS HWP=0.2772;AC=23;culprit=QD;MQ0=0;ReadPosRankSum=0.438;AN=200;InbreedingCoeff=-0.0464;AF=0.062;GQ_STDDEV=501.03;FS=1.63;DP=29792;GQ_MEAN=225.89;POSITIVE_TRAIN_SITE;VQSLOD=4.2;ClippingRankSum=-0.08;BaseQRankSum=5.93;MLEAF=0.062;MLEAC=108;MQ=59.7;QD=17.28;DB;MQRankSum=0.339;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:43,0:43:75:0,75,1631 0/1:21,39:60:99:1237,0,588 0/0:21,0:21:60:0,60,900 0/1:40,34:74:99:1135,0,1236 0/0:29,0:29:69:0,69,1035 0/0:21,0:21:60:0,60,857 0/0:30,0:30:72:0,72,1080 0/1:25,28:53:99:901,0,755 0/0:24,0:24:66:0,66,990 0/1:25,27:52:99:857,0,761 0/0:25,0:25:60:0,60,888 0/0:22,0:22:60:0,60,900 0/0:41,0:41:99:0,99,1485 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:33,0:33:61:0,61,1132 0/1:44,52:96:99:1736,0,1360 0/0:28,0:28:75:0,75,1087 0/0:23,0:23:66:0,66,990 0/0:23,0:23:60:0,60,900 0/1:49,52:101:99:1690,0,1491 0/1:109,107:216:99:3816,0,3185 0/0:31,0:31:63:0,63,945 0/0:22,0:22:60:0,60,900 0/1:91,82:173:99:2712,0,2745 0/0:41,0:41:72:0,72,1080 0/1:53,58:111:99:2036,0,1477 0/0:22,0:22:60:0,60,800 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,752 0/0:31,0:31:60:0,60,900 0/1:100,124:224:99:4742,0,2893 0/0:35,0:35:75:0,75,1305 0/0:20,0:20:60:0,60,697 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:87:0,87,1305 0/0:38,0:38:96:0,96,1440 0/1:54,55:109:99:1833,0,1638 0/0:35,0:35:99:0,102,1530 0/0:26,0:26:69:0,69,1035 0/0:20,0:20:60:0,60,767 0/0:26,0:26:69:0,69,980 0/1:95,81:176:99:2688,0,2841 0/0:40,0:40:98:0,98,1485 0/1:81,76:157:99:2616,0,2409 0/1:64,77:141:99:2954,0,1997 0/0:31,0:31:74:0,74,1196 0/0:24,0:24:60:0,60,900 0/0:38,0:38:99:0,105,1494 0/0:23,0:23:60:0,60,900 0/1:70,52:122:99:1856,0,2075 0/0:22,0:22:60:0,60,900 0/0:27,0:27:75:0,75,940 0/0:39,0:39:60:0,60,900 0/0:34,0:34:80:0,80,1305 0/1:82,99:181:99:3275,0,2287 0/1:89,71:160:99:2515,0,2846 0/0:29,0:29:78:0,78,1170 0/1:65,74:139:99:2426,0,1966 0/0:21,0:21:60:0,60,900 0/0:27,0:27:78:0,78,993 0/0:27,0:27:64:0,64,1123 0/0:34,0:34:63:0,63,1123 0/1:46,42:88:99:1526,0,1461 0/0:20,0:20:60:0,60,759 0/0:33,0:33:75:0,75,1190 0/0:20,0:20:60:0,60,708 0/0:30,0:30:81:0,81,1215 0/0:20,0:20:60:0,60,740 0/0:23,0:23:63:0,63,897 0/0:21,0:21:60:0,60,785 0/0:24,0:24:63:0,63,898 0/0:22,0:22:60:0,60,900 0/1:54,66:120:99:2528,0,1614 0/1:50,49:99:99:1775,0,1510 0/0:20,0:20:60:0,60,734 0/0:35,0:35:75:0,75,1125 0/0:21,0:21:63:0,63,784 0/1:29,39:68:99:1518,0,829 0/0:25,0:25:60:0,60,900 0/1:75,53:128:99:1918,0,2402 0/0:21,0:21:60:0,60,883 0/0:21,0:21:60:0,60,849 0/0:28,0:28:78:0,78,1170 0/0:20,0:20:60:0,60,655 0/0:29,0:29:84:0,84,1260 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,676 0/0:23,0:23:62:0,62,863 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,838 0/0:21,0:21:60:0,60,900 +20 13695680 rs6110019 C T 910852.00 PASS HWP=0.3234;AC=56;culprit=FS;MQ0=0;ReadPosRankSum=0.768;AN=200;InbreedingCoeff=-0.0372;AF=0.242;GQ_STDDEV=1124.56;FS=0.0;DP=79059;GQ_MEAN=828.68;POSITIVE_TRAIN_SITE;VQSLOD=6.2;ClippingRankSum=-0.415;BaseQRankSum=-3.492;MLEAF=0.242;MLEAC=421;MQ=59.51;QD=14.07;DB;MQRankSum=0.244;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/1:69,52:121:99:1434,0,1955 0/1:90,49:139:99:1160,0,2471 0/1:68,54:122:99:1449,0,1882 0/1:57,68:125:99:1876,0,1597 0/0:29,0:29:69:0,69,1035 0/0:21,0:21:60:0,60,857 0/1:90,65:155:99:1735,0,2688 0/1:59,49:108:99:1272,0,1585 0/1:85,57:142:99:1467,0,2485 0/1:62,49:111:99:1330,0,1693 0/0:25,0:25:60:0,60,888 0/1:63,67:130:99:1610,0,1827 0/0:41,0:41:99:0,99,1485 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:121,86:207:99:2385,0,3403 0/0:61,0:61:63:0,63,945 0/0:28,0:28:75:0,75,1087 0/0:23,0:23:66:0,66,990 0/0:23,0:23:60:0,60,900 0/1:97,81:178:99:2308,0,2751 0/0:75,0:75:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:65,0:65:87:0,87,1305 0/0:41,0:41:72:0,72,1080 0/1:115,81:196:99:2065,0,3462 0/0:22,0:22:60:0,60,800 0/1:113,67:180:99:1713,0,3466 0/0:21,0:21:60:0,60,752 0/0:31,0:31:60:0,60,900 0/1:208,161:369:99:4322,0,6406 0/1:185,143:328:99:3937,0,5674 0/0:20,0:20:60:0,60,697 0/0:22,0:22:60:0,60,900 1/1:0,159:159:99:5384,477,0 1/1:0,164:164:99:5781,493,0 0/1:152,131:283:99:3750,0,4634 0/0:52,0:52:66:0,66,990 1/1:0,117:117:99:4201,351,0 0/1:124,101:225:99:2738,0,3598 0/0:20,0:20:60:0,60,767 0/1:117,103:220:99:2897,0,3673 0/0:80,0:80:81:0,81,1215 0/1:110,82:192:99:2270,0,3291 0/0:86,0:86:99:0,117,1755 0/0:65,0:65:63:0,63,945 0/0:31,0:31:74:0,74,1196 1/1:1,176:177:99:6052,495,0 0/1:110,69:179:99:1841,0,3358 0/1:108,86:194:99:2521,0,3259 0/0:60,0:60:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:27,0:27:75:0,75,940 0/0:39,0:39:60:0,60,900 0/1:111,92:203:99:2716,0,3601 0/1:152,114:266:99:3137,0,4726 0/0:80,0:80:60:0,60,900 1/1:0,160:160:99:5712,481,0 0/1:106,76:182:99:2145,0,3415 0/0:21,0:21:60:0,60,900 0/1:112,99:211:99:2818,0,3251 1/1:0,145:145:99:5036,436,0 0/1:91,84:175:99:2447,0,2711 0/0:43,0:43:60:0,60,900 0/0:20,0:20:60:0,60,759 0/1:166,130:296:99:3617,0,5272 0/0:20,0:20:60:0,60,708 0/1:173,157:330:99:4416,0,4892 0/1:86,94:180:99:2614,0,2754 0/1:216,152:368:99:4016,0,6061 0/0:21,0:21:60:0,60,785 0/0:24,0:24:63:0,63,898 0/0:22,0:22:60:0,60,900 0/1:117,88:205:99:2305,0,3520 0/0:37,0:37:63:0,63,945 0/1:109,82:191:99:2129,0,3398 0/0:35,0:35:75:0,75,1125 0/1:86,70:156:99:1846,0,2698 0/1:92,61:153:99:1573,0,2934 0/1:88,68:156:99:1822,0,2840 0/0:58,0:58:81:0,81,1215 0/1:124,90:214:99:2371,0,3891 0/1:157,148:305:99:4127,0,4753 0/1:57,60:117:99:1762,0,1632 0/0:20,0:20:60:0,60,655 0/1:92,85:177:99:2339,0,2622 0/1:169,136:305:99:3591,0,5251 0/1:71,60:131:99:1666,0,2009 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 1/1:0,137:137:99:4596,411,0 0/1:66,67:133:99:1785,0,1894 0/0:20,0:20:60:0,60,676 0/0:23,0:23:62:0,62,863 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,838 0/0:21,0:21:60:0,60,900 +20 13695824 . C CA 34343.20 PASS HWP=0.0;AC=17;culprit=QD;MQ0=0;ReadPosRankSum=-0.185;AN=200;InbreedingCoeff=-0.0961;AF=0.069;GQ_STDDEV=46.17;FS=1.929;DP=30064;GQ_MEAN=46.53;VQSLOD=1.58;ClippingRankSum=-0.391;BaseQRankSum=0.278;MLEAF=0.07;MLEAC=121;MQ=59.46;QD=3.54;MQRankSum=0.238;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:0:0,0,808 0/0:21,0:28:63:0,63,516 0/0:17,0:22:50:0,50,410 0/1:5,10:18:99:212,0,104 0/0:12,0:17:36:0,36,308 0/1:11,0:20:99:165,0,194 0/0:21,0:31:61:0,61,507 0/0:26,0:26:0:0,0,814 0/0:46,0:46:44:0,44,675 0/1:8,3:11:40:40,0,160 0/0:7,5:16:0:0,0,187 0/1:6,4:11:76:76,0,108 0/0:11,0:16:33:0,33,273 0/0:10,0:16:30:0,30,243 0/0:32,0:39:95:0,95,787 0/0:33,12:52:77:0,77,936 0/0:19,3:32:17:0,17,508 0/0:59,0:59:36:0,36,1732 0/1:16,18:41:99:325,0,364 0/0:37,0:49:99:0,113,954 0/0:23,0:31:69:0,69,566 0/0:17,9:37:0:0,0,484 0/0:21,0:25:65:0,65,551 0/0:7,0:7:12:0,12,180 0/0:15,0:15:30:0,30,450 0/0:42,0:42:0:0,0,1333 0/1:15,6:21:84:84,0,295 0/0:13,0:16:39:0,39,322 0/0:5,0:9:15:0,15,114 0/0:24,0:24:0:0,0,552 0/0:26,0:26:21:0,21,315 0/0:10,0:17:30:0,30,241 0/0:61,0:61:21:0,21,2024 0/1:10,9:25:99:144,0,233 0/0:73,0:73:75:0,75,1125 0/0:19,0:19:0:0,0,435 0/0:26,0:26:0:0,0,682 0/0:25,0:35:42:0,42,574 0/0:12,0:16:36:0,36,296 0/0:31,0:36:92:0,92,773 0/0:9,5:20:0:0,0,235 0/0:20,3:26:35:0,35,439 0/0:31,0:31:0:0,0,893 0/0:6,0:17:0:0,0,190 0/0:58,0:58:0:0,0,1905 0/1:7,8:18:90:205,0,90 0/0:13,0:19:39:0,39,323 0/1:14,13:33:99:207,0,327 0/1:9,8:17:99:138,0,152 0/0:16,2:24:4:0,4,421 0/0:43,0:43:0:0,0,1376 0/0:13,0:18:39:0,39,338 0/0:12,0:17:36:0,36,312 0/1:5,4:16:82:82,0,126 0/0:18,10:28:54:0,54,454 0/0:16,0:22:47:0,47,407 0/0:59,0:59:12:0,12,2016 0/0:31,0:31:63:0,63,945 0/0:18,0:24:54:0,54,445 0/1:16,17:37:99:281,0,345 0/0:34,0:34:0:0,0,1021 0/1:8,7:15:99:126,0,163 0/0:17,10:27:50:0,50,411 0/0:19,0:19:30:0,30,450 0/0:17,0:17:21:0,21,315 0/0:23,0:37:21:0,21,518 0/1:8,4:12:84:84,0,154 0/0:16,0:16:24:0,24,360 0/0:24,3:33:28:0,28,614 0/0:13,0:17:39:0,39,336 0/0:18,0:24:54:0,54,467 0/0:18,0:22:54:0,54,452 0/0:20,0:31:57:0,57,461 0/0:13,0:21:39:0,39,324 0/0:20,0:25:60:0,60,514 0/0:12,0:16:36:0,36,313 0/0:12,0:17:36:0,36,296 0/1:9,4:13:60:60,0,164 0/0:13,3:25:0:0,0,352 0/0:21,0:32:0:0,0,524 0/0:9,0:12:27:0,27,219 0/1:5,6:11:98:100,0,98 0/0:34,0:34:24:0,24,360 0/1:10,7:19:99:115,0,224 0/0:10,0:16:30:0,30,260 0/0:21,0:28:63:0,63,548 0/0:7,0:12:21:0,21,182 0/0:9,0:9:21:0,21,315 0/0:20,6:36:0:0,0,526 0/0:14,0:18:41:0,41,333 0/0:12,0:12:21:0,21,315 0/0:15,0:20:44:0,44,374 0/0:13,3:16:38:0,38,320 0/0:22,0:22:0:0,0,575 0/0:13,0:19:39:0,39,339 0/0:9,0:9:0:0,0,185 0/0:6,0:9:18:0,18,156 0/0:9,0:13:26:0,26,202 0/0:9,0:12:27:0,27,235 0/0:20,0:24:60:0,60,501 +20 13695824 . CA C 34343.20 PASS HWP=0.0;AC=55;culprit=QD;MQ0=0;ReadPosRankSum=-0.185;AN=200;InbreedingCoeff=-0.0961;AF=0.217;GQ_STDDEV=46.17;FS=1.929;DP=30064;GQ_MEAN=46.53;VQSLOD=1.58;ClippingRankSum=-0.391;BaseQRankSum=0.278;MLEAF=0.232;MLEAC=404;MQ=59.46;QD=3.54;MQRankSum=0.238;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:0:0,0,808 0/1:21,7:28:99:100,0,430 0/1:17,5:22:67:67,0,344 0/0:5,3:18:0:0,0,278 0/1:12,5:17:82:82,0,255 0/0:11,0:20:33:0,33,255 0/1:21,10:31:99:140,0,415 0/0:26,0:26:0:0,0,814 0/0:46,0:46:44:0,44,675 0/0:8,0:11:26:0,26,194 0/1:7,4:16:64:64,0,221 0/0:6,0:11:10:0,10,129 0/1:11,5:16:82:82,0,223 0/1:10,6:16:79:79,0,195 0/1:32,7:39:50:50,0,669 0/1:33,4:52:99:199,0,756 0/1:19,10:32:99:115,0,453 0/0:59,0:59:36:0,36,1732 0/0:16,7:41:0:0,0,479 0/1:37,12:49:99:119,0,803 0/1:23,8:31:99:119,0,471 0/1:17,6:37:99:185,0,430 0/1:21,4:25:29:29,0,471 0/0:7,0:7:12:0,12,180 0/0:15,0:15:30:0,30,450 0/0:42,0:42:0:0,0,1333 0/0:15,0:21:46:0,46,360 0/1:13,3:16:33:33,0,271 0/1:5,4:9:80:80,0,85 0/0:24,0:24:0:0,0,552 0/0:26,0:26:21:0,21,315 0/1:10,7:17:99:134,0,189 0/0:61,0:61:21:0,21,2024 0/0:10,6:25:0:0,0,323 0/0:73,0:73:75:0,75,1125 0/0:19,0:19:0:0,0,435 0/0:26,0:26:0:0,0,682 0/1:25,6:35:97:97,0,514 0/1:12,4:16:42:42,0,247 0/1:31,5:36:27:27,0,663 0/1:9,6:20:99:101,0,225 0/0:20,3:26:0:0,0,395 0/0:31,0:31:0:0,0,893 0/1:6,8:17:99:146,0,138 0/0:58,0:58:0:0,0,1905 0/0:7,0:18:0:0,0,113 0/1:13,6:19:99:101,0,264 0/0:14,6:33:0:0,0,445 0/0:9,0:17:29:0,29,208 0/1:16,6:24:64:64,0,416 0/0:43,0:43:0:0,0,1376 0/1:13,5:18:79:79,0,283 0/1:12,5:17:66:66,0,259 0/0:5,4:16:0:0,0,153 0/1:18,0:28:99:180,0,367 0/1:16,6:22:74:74,0,340 0/0:59,0:59:12:0,12,2016 0/0:31,0:31:63:0,63,945 0/1:18,6:24:72:72,0,371 0/0:16,4:37:12:0,12,495 0/0:34,0:34:0:0,0,1021 0/0:8,0:15:26:0,26,210 0/1:17,0:27:99:153,0,328 0/0:19,0:19:30:0,30,450 0/0:17,0:17:21:0,21,315 0/1:23,8:37:99:164,0,473 0/0:8,0:12:25:0,25,194 0/0:16,0:16:24:0,24,360 0/1:24,6:33:41:41,0,603 0/1:13,4:17:56:56,0,282 0/1:18,6:24:65:65,0,395 0/1:18,4:22:26:26,0,385 0/1:20,11:31:99:169,0,369 0/1:13,8:21:99:148,0,259 0/1:20,5:25:38:38,0,437 0/1:12,4:16:58:58,0,263 0/1:12,5:17:82:82,0,244 0/0:9,0:13:27:0,27,203 0/1:13,9:25:99:144,0,317 0/1:21,7:32:59:59,0,460 0/1:9,3:12:44:44,0,182 0/0:5,0:11:17:0,17,132 0/0:34,0:34:24:0,24,360 0/0:10,2:19:0:0,0,274 0/1:10,6:16:91:91,0,211 0/1:21,7:28:70:70,0,461 0/1:7,5:12:80:80,0,145 0/0:9,0:9:21:0,21,315 0/1:20,5:36:97:97,0,530 0/1:14,4:18:53:53,0,277 0/0:12,0:12:21:0,21,315 0/1:15,5:20:73:73,0,314 0/1:13,0:16:33:33,0,271 0/0:22,0:22:0:0,0,575 0/1:13,6:19:86:86,0,281 0/0:9,0:9:0:0,0,185 0/1:6,3:9:53:53,0,128 0/1:9,4:13:68:68,0,162 0/1:9,3:12:44:44,0,197 0/1:20,4:24:35:35,0,427 +20 13695824 . CAA C 34343.20 PASS HWP=0.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=-0.185;AN=200;InbreedingCoeff=-0.0961;AF=0.00977;GQ_STDDEV=46.17;FS=1.929;DP=30064;GQ_MEAN=46.53;VQSLOD=1.58;ClippingRankSum=-0.391;BaseQRankSum=0.278;MLEAF=0.007471;MLEAC=13;MQ=59.46;QD=3.54;MQRankSum=0.238;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:0:0,0,808 0/0:21,0:28:63:0,63,516 0/0:17,0:22:50:0,50,410 0/0:5,0:18:15:0,15,128 0/0:12,0:17:36:0,36,308 0/0:11,9:20:33:0,33,255 0/0:21,0:31:61:0,61,507 0/0:26,0:26:0:0,0,814 0/0:46,0:46:44:0,44,675 0/0:8,0:11:26:0,26,194 0/0:7,0:16:21:0,21,182 0/0:6,0:11:10:0,10,129 0/0:11,0:16:33:0,33,273 0/0:10,0:16:30:0,30,243 0/0:32,0:39:95:0,95,787 0/0:33,3:52:0:0,0,1210 0/0:19,0:32:57:0,57,491 0/0:59,0:59:36:0,36,1732 0/0:16,0:41:48:0,48,412 0/0:37,0:49:99:0,113,954 0/0:23,0:31:69:0,69,566 0/0:17,5:37:0:0,0,764 0/0:21,0:25:65:0,65,551 0/0:7,0:7:12:0,12,180 0/0:15,0:15:30:0,30,450 0/0:42,0:42:0:0,0,1333 0/0:15,0:21:46:0,46,360 0/0:13,0:16:39:0,39,322 0/0:5,0:9:15:0,15,114 0/0:24,0:24:0:0,0,552 0/0:26,0:26:21:0,21,315 0/0:10,0:17:30:0,30,241 0/0:61,0:61:21:0,21,2024 0/0:10,0:25:30:0,30,240 0/0:73,0:73:75:0,75,1125 0/0:19,0:19:0:0,0,435 0/0:26,0:26:0:0,0,682 0/0:25,4:35:0:0,0,851 0/0:12,0:16:36:0,36,296 0/0:31,0:36:92:0,92,773 0/0:9,0:20:27:0,27,232 0/1:20,0:26:41:41,0,639 0/0:31,0:31:0:0,0,893 0/0:6,3:17:18:0,18,155 0/0:58,0:58:0:0,0,1905 0/0:7,3:18:0:0,0,113 0/0:13,0:19:39:0,39,323 0/0:14,0:33:42:0,42,361 0/0:9,0:17:29:0,29,208 0/0:16,0:24:48:0,48,413 0/0:43,0:43:0:0,0,1376 0/0:13,0:18:39:0,39,338 0/0:12,0:17:36:0,36,312 0/0:5,0:16:0:0,0,106 0/0:18,0:28:54:0,54,454 0/0:16,0:22:47:0,47,407 0/0:59,0:59:12:0,12,2016 0/0:31,0:31:63:0,63,945 0/0:18,0:24:54:0,54,445 0/0:16,0:37:48:0,48,411 0/0:34,0:34:0:0,0,1021 0/0:8,0:15:26:0,26,210 0/0:17,0:27:50:0,50,411 0/0:19,0:19:30:0,30,450 0/0:17,0:17:21:0,21,315 0/0:23,6:37:0:0,0,747 0/0:8,0:12:25:0,25,194 0/0:16,0:16:24:0,24,360 0/0:24,0:33:72:0,72,620 0/0:13,0:17:39:0,39,336 0/0:18,0:24:54:0,54,467 0/0:18,0:22:54:0,54,452 0/0:20,0:31:57:0,57,461 0/0:13,0:21:39:0,39,324 0/0:20,0:25:60:0,60,514 0/0:12,0:16:36:0,36,313 0/0:12,0:17:36:0,36,296 0/0:9,0:13:27:0,27,203 0/0:13,0:25:39:0,39,336 0/0:21,4:32:62:0,62,510 0/0:9,0:12:27:0,27,219 0/0:5,0:11:17:0,17,132 0/0:34,0:34:24:0,24,360 0/0:10,0:19:30:0,30,258 0/0:10,0:16:30:0,30,260 0/0:21,0:28:63:0,63,548 0/0:7,0:12:21:0,21,182 0/0:9,0:9:21:0,21,315 0/0:20,5:36:0:0,0,917 0/0:14,0:18:41:0,41,333 0/0:12,0:12:21:0,21,315 0/0:15,0:20:44:0,44,374 0/0:13,0:16:38:0,38,320 0/0:22,0:22:0:0,0,575 0/0:13,0:19:39:0,39,339 0/0:9,0:9:0:0,0,185 0/0:6,0:9:18:0,18,156 0/0:9,0:13:26:0,26,202 0/0:9,0:12:27:0,27,235 0/0:20,0:24:60:0,60,501 +20 13698006 rs4239710 T C 4600810.00 PASS HWP=0.043;AC=200;culprit=QD;MQ0=0;ReadPosRankSum=0.675;AN=200;InbreedingCoeff=0.1034;AF=0.973;GQ_STDDEV=371.52;FS=0.0;DP=133766;GQ_MEAN=524.01;POSITIVE_TRAIN_SITE;VQSLOD=4.88;ClippingRankSum=-0.072;BaseQRankSum=1.53;MLEAF=0.973;MLEAC=1693;MQ=59.56;QD=34.54;DB;MQRankSum=0.381;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,119:119:99:4137,358,0 1/1:0,134:134:99:4616,403,0 1/1:0,107:107:99:3560,321,0 1/1:0,140:140:99:4789,420,0 1/1:0,130:130:99:4522,391,0 1/1:0,154:154:99:5170,462,0 1/1:0,151:151:99:5532,454,0 1/1:0,110:110:99:3730,331,0 1/1:0,139:139:99:4799,418,0 1/1:0,109:109:99:3723,328,0 1/1:0,117:117:99:4331,352,0 1/1:1,84:85:99:2835,249,0 1/1:0,130:130:99:4921,390,0 1/1:0,95:95:99:3381,286,0 1/1:0,101:101:99:3486,304,0 1/1:0,156:156:99:5278,469,0 1/1:0,140:140:99:4739,421,0 1/1:0,175:175:99:5883,526,0 1/1:0,132:132:99:4583,396,0 1/1:0,226:226:99:7393,679,0 1/1:0,145:145:99:4900,435,0 1/1:1,184:185:99:6251,530,0 1/1:0,180:180:99:6086,541,0 1/1:0,396:396:99:13420,1188,0 1/1:0,353:353:99:12707,1059,0 1/1:0,160:160:99:5782,481,0 1/1:0,202:202:99:7449,607,0 1/1:0,183:183:99:6589,550,0 1/1:0,175:175:99:6224,525,0 1/1:0,161:161:99:5808,484,0 1/1:0,132:132:99:4728,397,0 1/1:0,127:127:99:4542,382,0 1/1:1,258:259:99:9512,736,0 1/1:0,293:293:99:11170,881,0 1/1:0,284:284:99:10387,853,0 1/1:0,144:144:99:4606,432,0 1/1:0,124:124:99:4360,372,0 1/1:0,203:203:99:6785,610,0 1/1:0,122:122:99:4580,367,0 1/1:0,191:191:99:7125,574,0 1/1:0,101:101:99:3681,304,0 1/1:0,136:136:99:4939,409,0 1/1:0,155:155:99:5648,466,0 1/1:0,128:128:99:4721,385,0 1/1:0,153:153:99:5724,460,0 1/1:1,182:183:99:6674,518,0 1/1:0,160:160:99:6112,481,0 1/1:0,158:158:99:5991,475,0 1/1:0,255:255:99:9804,766,0 1/1:0,257:257:99:9474,772,0 1/1:0,158:158:99:5986,475,0 1/1:0,143:143:99:5350,430,0 1/1:0,129:129:99:4669,387,0 1/1:0,174:174:99:6150,523,0 1/1:0,233:233:99:8750,700,0 1/1:0,196:196:99:6994,589,0 1/1:0,163:163:99:5967,490,0 1/1:0,167:167:99:6338,502,0 1/1:0,216:216:99:7761,649,0 1/1:0,219:219:99:8498,658,0 1/1:0,147:147:99:5452,442,0 1/1:0,170:170:99:6262,511,0 1/1:0,262:262:99:10219,787,0 1/1:0,153:153:99:5626,460,0 1/1:0,142:142:99:5199,427,0 1/1:1,169:170:99:5763,484,0 1/1:0,97:97:99:3510,291,0 1/1:0,91:91:99:3196,273,0 1/1:0,193:193:99:7547,580,0 1/1:0,125:125:99:4730,376,0 1/1:0,254:254:99:9698,764,0 1/1:0,139:139:99:5219,418,0 1/1:0,255:255:99:9158,765,0 1/1:0,128:128:99:4924,385,0 1/1:1,160:161:99:6136,474,0 1/1:0,114:114:99:4291,343,0 1/1:0,170:170:99:6113,511,0 1/1:0,150:150:99:5721,450,0 1/1:0,155:155:99:5519,465,0 1/1:0,180:180:99:6415,539,0 1/1:0,98:98:99:3478,294,0 1/1:0,93:93:99:3373,279,0 1/1:0,103:103:99:3683,309,0 1/1:0,164:164:99:5972,493,0 1/1:0,163:163:99:6187,490,0 1/1:0,240:240:99:8538,721,0 1/1:0,135:135:99:4547,405,0 1/1:0,135:135:99:4668,405,0 1/1:0,178:178:99:6168,535,0 1/1:0,264:264:99:9969,794,0 1/1:0,156:156:99:5078,468,0 1/1:0,159:159:99:5266,477,0 1/1:0,132:132:99:5096,396,0 1/1:0,98:98:99:3789,294,0 1/1:0,152:152:99:5075,456,0 1/1:0,114:114:99:3842,342,0 1/1:0,102:102:99:3972,306,0 1/1:0,113:113:99:4377,339,0 1/1:0,114:114:99:4229,343,0 1/1:0,163:163:99:6174,490,0 +20 13698129 rs78509779 G A 6545.32 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.391;AN=200;InbreedingCoeff=-0.0023;AF=0.002299;GQ_STDDEV=111.9;FS=3.29;DP=37193;GQ_MEAN=91.69;POSITIVE_TRAIN_SITE;VQSLOD=4.29;ClippingRankSum=-1.653;BaseQRankSum=-1.305;MLEAF=0.002299;MLEAC=4;MQ=60.0;QD=14.17;DB;MQRankSum=0.803;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:38,0:38:99:0,102,1530 0/0:34,0:34:69:0,69,1035 0/0:46,0:46:96:0,96,1440 0/0:45,0:45:99:0,102,1530 0/0:28,0:28:69:0,69,1035 0/0:45,0:45:99:0,105,1575 0/0:38,0:38:96:0,96,1440 0/0:31,0:31:60:0,60,900 0/0:38,0:38:90:0,90,1350 0/0:29,0:29:60:0,60,900 0/0:26,0:26:72:0,72,1080 0/0:32,0:32:78:0,78,1170 0/0:39,0:39:96:0,96,1440 0/0:27,0:27:60:0,60,900 0/0:49,0:49:99:0,117,1755 0/0:43,0:43:63:0,63,1395 0/0:41,0:41:81:0,81,1215 0/0:40,0:40:90:0,90,1350 0/0:28,0:28:69:0,69,1035 0/0:48,0:48:99:0,120,1800 0/0:41,0:41:84:0,84,1260 0/0:47,0:47:99:0,114,1710 0/0:48,0:48:93:0,93,1395 0/0:73,0:73:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:50,0:50:99:0,117,1755 0/0:63,0:63:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:39,0:39:87:0,87,1305 0/0:37,0:37:93:0,93,1395 0/0:29,0:29:75:0,75,1125 0/0:33,0:33:60:0,60,900 0/0:80,0:80:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:24,0:24:66:0,66,990 0/0:42,0:42:87:0,87,1305 0/0:39,0:39:84:0,84,1260 0/0:55,0:55:99:0,120,1800 0/0:38,0:38:69:0,69,1035 0/0:45,0:45:95:0,95,1527 0/0:44,0:44:98:0,98,1485 0/0:60,0:60:99:0,120,1800 0/0:48,0:48:99:0,111,1755 0/0:75,0:75:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:51,0:51:99:0,108,1620 0/0:59,0:59:99:0,120,1800 0/0:39,0:39:99:0,99,1485 0/0:48,0:48:82:0,82,1710 0/0:38,0:38:93:0,93,1395 0/0:51,0:51:99:0,108,1620 0/0:55,0:55:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:48,0:48:99:0,117,1755 0/0:52,0:52:99:0,120,1800 0/0:40,0:40:99:0,99,1485 0/0:29,0:29:72:0,72,1080 0/0:28,0:28:63:0,63,945 0/0:67,0:67:99:0,120,1800 0/0:42,0:42:98:0,98,1530 0/0:55,0:55:99:0,120,1800 0/0:32,0:32:60:0,60,900 0/0:68,0:68:99:0,104,1800 0/0:52,0:52:99:0,117,1755 0/0:37,0:37:93:0,93,1395 0/0:30,0:30:63:0,63,945 0/0:37,0:37:83:0,83,1260 0/0:38,0:38:93:0,93,1395 0/0:37,0:37:93:0,93,1395 0/0:54,0:54:99:0,120,1800 0/0:32,0:32:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:37,0:37:75:0,75,1125 0/0:54,0:54:99:0,113,1800 0/0:39,0:39:93:0,93,1395 0/0:57,0:57:99:0,120,1800 0/0:64,0:64:76:0,76,1800 0/0:28,0:28:60:0,60,900 0/0:34,0:34:69:0,69,1035 0/0:83,0:83:99:0,120,1800 0/0:32,0:32:63:0,63,945 0/1:41,46:87:99:1376,0,1217 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:75:0,75,1125 0/0:29,0:29:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:33,0:33:65:0,65,1260 0/1:41,33:74:99:1069,0,1368 0/0:45,0:45:99:0,102,1530 +20 13709115 . T C 1206.72 PASS NEGATIVE_TRAIN_SITE;HWP=1.0;AC=1;culprit=ReadPosRankSum;MQ0=0;ReadPosRankSum=-2.392;AN=200;InbreedingCoeff=-0.0019;AF=5.747E-4;GQ_STDDEV=27.18;FS=1.573;DP=17910;GQ_MEAN=49.59;VQSLOD=0.438;ClippingRankSum=2.02;BaseQRankSum=4.26;MLEAF=5.747E-4;MLEAC=1;MQ=59.02;QD=19.46;MQRankSum=1.27;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,785 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,866 0/0:28,0:28:64:0,64,1035 0/0:33,0:33:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:38,0:38:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:29,0:29:69:0,69,1035 0/0:10,0:10:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:37,0:37:60:0,60,900 0/0:32,0:32:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:20,0:20:60:0,60,753 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:9,0:9:24:0,24,360 0/0:11,0:11:24:0,24,360 0/0:24,0:24:63:0,63,945 0/0:20,0:20:60:0,60,783 0/0:23,0:23:60:0,60,900 0/0:30,0:30:75:0,75,1125 0/0:26,0:26:63:0,63,945 0/0:24,0:24:61:0,61,938 0/0:27,0:27:63:0,63,945 0/0:30,0:30:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:9,0:9:24:0,24,334 0/0:11,0:11:21:0,21,315 0/0:21,0:21:60:0,60,764 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:24,0:24:69:0,69,909 0/0:25,0:25:60:0,60,900 0/0:31,0:31:68:0,68,1035 0/0:22,0:22:60:0,60,854 0/0:24,0:24:60:0,60,880 0/0:34,0:34:62:0,62,945 0/0:26,0:26:63:0,63,929 0/0:8,0:8:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:18,0:18:27:0,27,405 0/0:13,0:13:24:0,24,360 0/0:27,0:27:63:0,63,945 0/0:15,0:15:27:0,27,405 0/0:30,0:30:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/1:24,38:62:99:1257,0,637 0/0:21,0:21:60:0,60,792 0/0:28,0:28:63:0,63,945 0/0:10,0:10:21:0,21,315 0/0:22,0:22:60:0,60,802 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,801 0/0:20,0:20:60:0,60,735 0/0:13,0:13:21:0,21,315 0/0:22,0:22:60:0,60,867 0/0:11,0:11:24:0,24,360 0/0:20,0:20:60:0,60,760 0/0:26,0:26:66:0,66,990 0/0:32,0:32:63:0,63,945 0/0:21,0:21:60:0,60,751 0/0:9,0:9:21:0,21,315 0/0:31,0:31:66:0,66,990 0/0:30,0:30:69:0,69,1035 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,250 0/0:22,0:22:66:0,66,803 0/0:11,0:11:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:27,0:27:72:0,72,978 0/0:10,0:10:21:0,21,315 0/0:24,0:24:60:0,60,900 +20 13714384 rs41275402 A C 5153.32 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.243;AN=200;InbreedingCoeff=-0.0023;AF=0.002299;GQ_STDDEV=87.91;FS=4.703;DP=31662;GQ_MEAN=88.98;POSITIVE_TRAIN_SITE;VQSLOD=3.18;ClippingRankSum=-0.024;BaseQRankSum=3.15;MLEAF=0.002299;MLEAC=4;MQ=59.52;QD=14.04;DB;MQRankSum=1.07;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:75:0,75,1125 0/0:32,0:32:93:0,93,1395 0/0:24,0:24:60:0,60,900 0/0:24,0:24:68:0,68,885 0/0:23,0:23:66:0,66,990 0/0:24,0:24:69:0,69,1035 0/0:21,0:21:63:0,63,795 0/0:27,0:27:78:0,78,1146 0/0:24,0:24:63:0,63,945 0/0:27,0:27:78:0,78,1037 0/0:32,0:32:63:0,63,1172 0/0:21,0:21:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:22,0:22:63:0,63,945 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:81:0,81,1063 0/0:20,0:20:60:0,60,744 0/0:34,0:34:90:0,90,1350 0/0:23,0:23:63:0,63,945 0/0:28,0:28:81:0,81,1142 0/0:35,0:35:66:0,66,1208 0/0:27,0:27:68:0,68,1149 0/0:33,0:33:61:0,61,1154 0/0:37,0:37:99:0,108,1620 0/0:37,0:37:78:0,78,1380 0/0:61,0:61:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:45,0:45:62:0,62,1710 0/0:30,0:30:72:0,72,1025 0/0:23,0:23:69:0,69,863 0/0:57,0:57:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:20,0:20:60:0,60,781 0/0:24,0:24:60:0,60,900 0/0:27,0:27:78:0,78,1170 0/0:40,0:40:99:0,117,1755 0/0:66,0:66:99:0,120,1800 0/0:44,0:44:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/1:54,47:101:99:1471,0,1804 0/0:76,0:76:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:40,0:40:99:0,108,1620 0/0:49,0:49:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/0:25,0:25:69:0,69,1035 0/0:42,0:42:99:0,114,1710 0/0:57,0:57:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:28,0:28:75:0,75,1125 0/0:26,0:26:66:0,66,990 0/0:25,0:25:72:0,72,1080 0/0:60,0:60:99:0,120,1800 0/0:41,0:41:99:0,114,1710 0/0:61,0:61:99:0,120,1800 0/0:30,0:30:84:0,84,1260 0/0:58,0:58:99:0,120,1800 0/0:37,0:37:99:0,108,1620 0/0:36,0:36:99:0,102,1530 0/0:31,0:31:81:0,81,1215 0/0:32,0:32:96:0,96,1251 0/0:33,0:33:96:0,96,1440 0/0:36,0:36:99:0,99,1485 0/0:42,0:42:99:0,108,1620 0/0:21,0:21:60:0,60,772 0/0:23,0:23:60:0,60,848 0/0:30,0:30:87:0,87,1227 0/0:39,0:39:99:0,111,1665 0/0:36,0:36:99:0,99,1485 0/0:41,0:41:99:0,105,1575 0/0:21,0:21:60:0,60,783 0/0:22,0:22:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:72,0:72:99:0,120,1800 0/0:34,0:34:65:0,65,1160 0/0:24,0:24:60:0,60,900 0/0:41,0:41:99:0,108,1620 0/0:27,0:27:78:0,78,1170 0/0:20,0:20:60:0,60,810 0/0:24,0:24:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:29,0:29:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:36,0:36:99:0,103,1348 +20 13740447 rs146733330 CCTT C 7508.95 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.207;AN=200;InbreedingCoeff=-0.0066;AF=0.005747;GQ_STDDEV=84.19;FS=1.107;DP=19677;GQ_MEAN=63.22;POSITIVE_TRAIN_SITE;VQSLOD=3.94;ClippingRankSum=0.031;BaseQRankSum=0.763;MLEAF=0.005747;MLEAC=10;MQ=57.26;QD=16.32;DB;MQRankSum=-0.406;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:21,0:21:63:0,63,724 0/0:15,0:15:20:0,20,577 0/0:21,0:21:60:0,60,900 0/0:25,0:25:69:0,69,1035 0/0:15,0:15:36:0,36,540 0/0:24,0:24:40:0,40,856 0/0:20,0:20:38:0,38,751 0/0:18,0:18:23:0,23,574 0/0:29,0:29:43:0,43,1065 0/0:10,0:10:24:0,24,360 0/0:13,0:13:33:0,33,495 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:17,0:17:39:0,39,585 0/0:31,0:31:78:0,78,1170 0/0:25,0:25:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:37,0:37:90:0,90,1350 0/0:35,0:35:71:0,71,1145 0/0:32,0:32:78:0,78,1170 0/0:35,0:35:67:0,67,1149 0/0:24,0:24:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:29,0:29:61:0,61,1035 0/0:28,0:28:60:0,60,900 0/0:33,0:33:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:9,0:9:21:0,21,315 0/0:29,0:29:75:0,75,1125 0/0:26,0:26:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:22,0:22:60:0,60,885 0/0:9,0:9:21:0,21,315 0/0:30,0:30:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:29,0:29:62:0,62,1080 0/0:29,0:29:69:0,69,1035 0/0:25,0:25:63:0,63,945 0/0:32,0:32:69:0,69,1035 0/0:27,0:27:66:0,66,967 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,838 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:34,0:34:72:0,72,1170 0/0:22,0:22:60:0,60,900 0/0:25,0:25:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:66:0,66,933 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:62:0,62,1129 0/0:26,0:26:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:8,0:8:21:0,21,275 0/0:26,0:26:63:0,63,945 0/0:12,0:12:33:0,33,461 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:20,0:20:51:0,51,765 0/0:22,0:22:60:0,60,848 0/0:8,0:8:21:0,21,291 0/0:22,0:22:60:0,60,900 0/0:17,0:17:39:0,39,585 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,707 0/0:21,0:21:60:0,60,794 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,896 0/0:24,0:24:63:0,63,931 0/1:7,8:15:99:307,0,342 0/0:7,0:7:21:0,21,260 0/1:24,22:46:99:817,0,1138 0/0:22,0:22:60:0,60,900 0/0:14,0:14:33:0,33,495 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:10,0:10:27:0,27,405 0/0:22,0:22:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:9,0:9:27:0,27,331 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:63:0,63,945 +20 13747441 rs3180370 A G 2292420.00 PASS HWP=0.6068;AC=152;culprit=FS;MQ0=0;ReadPosRankSum=0.372;AN=200;InbreedingCoeff=0.0202;AF=0.81;GQ_STDDEV=544.43;FS=0.0;DP=76913;GQ_MEAN=537.97;POSITIVE_TRAIN_SITE;VQSLOD=5.61;ClippingRankSum=-0.082;BaseQRankSum=4.02;MLEAF=0.81;MLEAC=1410;MQ=59.7;QD=30.57;DB;MQRankSum=0.189;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:36,41:77:99:1145,0,1036 1/1:0,80:80:99:3059,240,0 0/1:22,27:49:99:833,0,595 1/1:0,74:74:99:2735,223,0 0/1:45,37:82:99:1145,0,1211 1/1:0,76:76:99:2909,229,0 0/1:44,43:87:99:1516,0,1279 1/1:0,62:62:99:2464,187,0 0/1:41,47:88:99:1528,0,1110 1/1:3,63:66:99:2417,155,0 0/1:47,38:85:99:1233,0,1216 1/1:0,58:58:99:2103,174,0 0/1:36,38:74:99:1179,0,1079 1/1:2,71:73:99:2641,192,0 1/1:0,76:76:99:2722,228,0 0/1:54,46:100:99:1287,0,1495 1/1:0,74:74:99:2705,223,0 1/1:0,98:98:99:3479,294,0 0/1:50,43:93:99:1373,0,1380 1/1:0,126:126:99:4669,379,0 1/1:1,106:107:99:3651,287,0 0/1:61,44:105:99:1316,0,1778 1/1:0,103:103:99:3847,310,0 0/1:112,89:201:99:2565,0,3024 0/0:83,0:83:99:0,120,1800 1/1:0,109:109:99:4131,327,0 0/1:42,51:93:99:1553,0,1091 0/0:46,0:46:99:0,120,1800 1/1:0,106:106:99:4194,318,0 1/1:0,106:106:99:4153,319,0 0/1:46,52:98:99:1666,0,1198 1/1:0,57:57:99:2132,171,0 0/1:66,81:147:99:2695,0,1738 1/1:0,160:160:99:6567,481,0 0/1:86,75:161:99:2527,0,2481 1/1:2,76:78:99:2693,161,0 1/1:0,64:64:99:2353,192,0 1/1:0,113:113:99:4021,339,0 1/1:0,91:91:99:3416,273,0 1/1:0,107:107:99:3973,321,0 1/1:0,81:81:99:3020,244,0 1/1:0,61:61:99:2380,184,0 1/1:0,79:79:99:3013,238,0 0/1:31,45:76:99:1571,0,857 0/1:55,54:109:99:1750,0,1601 0/1:60,66:126:99:2008,0,1736 0/1:57,55:112:99:1714,0,1645 1/1:0,117:117:99:4518,352,0 1/1:0,140:140:99:5586,421,0 0/0:85,0:85:99:0,120,1800 1/1:0,99:99:99:3775,297,0 0/1:50,55:105:99:1798,0,1436 1/1:0,77:77:99:2914,232,0 1/1:0,88:88:99:3450,264,0 1/1:0,111:111:99:4382,334,0 0/1:35,48:83:99:1536,0,896 0/0:63,0:63:99:0,120,1800 1/1:0,114:114:99:4404,342,0 1/1:0,143:143:99:5431,430,0 0/1:66,80:146:99:2961,0,1948 1/1:0,71:71:99:2692,214,0 1/1:0,84:84:99:3131,253,0 0/1:78,92:170:99:3254,0,2154 0/1:42,43:85:99:1365,0,1091 1/1:0,81:81:99:3138,243,0 0/1:50,73:123:99:2224,0,1367 0/1:23,47:70:99:1698,0,586 0/1:29,30:59:99:1056,0,821 0/1:71,75:146:99:2511,0,2090 0/0:26,0:26:66:0,66,1035 1/1:4,126:130:99:5296,379,0 1/1:0,66:66:99:2761,199,0 0/1:72,72:144:99:2377,0,1940 0/1:38,40:78:99:1360,0,1035 0/1:40,49:89:99:1591,0,1105 0/1:42,34:76:99:1086,0,1151 1/1:0,101:101:99:3942,304,0 0/1:35,31:66:99:1015,0,963 0/1:41,53:94:99:1753,0,1133 0/0:55,0:55:99:0,120,1800 1/1:0,57:57:99:2264,171,0 1/1:0,57:57:99:2171,170,0 1/1:0,49:49:99:1969,147,0 0/1:65,40:105:99:1216,0,1866 1/1:1,71:72:99:2830,178,0 0/1:63,56:119:99:1838,0,1788 1/1:0,56:56:99:1950,168,0 1/1:0,62:62:99:2159,186,0 1/1:0,109:109:99:3903,327,0 1/1:0,145:145:99:5789,436,0 1/1:0,68:68:99:2501,204,0 1/1:1,67:68:99:2475,167,0 1/1:1,73:74:99:2941,186,0 1/1:0,62:62:99:2476,186,0 1/1:0,86:86:99:3064,258,0 1/1:1,53:54:99:1862,125,0 1/1:0,62:62:99:2409,186,0 1/1:0,75:75:99:2934,226,0 1/1:0,52:52:99:2044,156,0 1/1:0,71:71:99:2894,214,0 +20 13753124 rs2274674 A C 451986.00 PASS HWP=0.0496;AC=42;culprit=MQ;MQ0=0;ReadPosRankSum=0.392;AN=200;InbreedingCoeff=0.0699;AF=0.233;GQ_STDDEV=449.51;FS=0.0;DP=39825;GQ_MEAN=329.01;POSITIVE_TRAIN_SITE;VQSLOD=7.24;ClippingRankSum=-0.32;BaseQRankSum=4.86;MLEAF=0.233;MLEAC=405;MQ=60.0;QD=20.91;DB;MQRankSum=0.188;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:25,23:48:99:777,0,682 1/1:0,49:49:99:1866,147,0 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:24,0:24:63:0,63,945 0/1:22,21:43:99:724,0,659 1/1:1,35:36:74:1328,74,0 0/0:28,0:28:70:0,70,1080 0/0:29,0:29:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/1:23,23:46:99:827,0,690 0/0:26,0:26:60:0,60,900 0/0:34,0:34:72:0,72,1080 0/1:29,28:57:99:909,0,877 0/1:23,23:46:99:747,0,698 0/0:31,0:31:72:0,72,1080 0/0:31,0:31:69:0,69,1035 0/0:27,0:27:72:0,72,1080 1/1:0,48:48:99:1868,144,0 0/0:26,0:26:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:28,0:28:63:0,63,945 0/0:43,0:43:81:0,81,1215 1/1:0,91:91:99:3542,274,0 0/0:50,0:50:99:0,114,1710 0/0:42,0:42:99:0,99,1485 0/0:33,0:33:63:0,63,945 1/1:1,71:72:99:2904,207,0 0/0:28,0:28:66:0,66,990 0/0:29,0:29:69:0,69,1035 0/0:59,0:59:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/1:13,18:31:99:626,0,324 0/0:31,0:31:72:0,72,1080 0/0:38,0:38:75:0,75,1125 0/0:44,0:44:99:0,105,1575 0/1:51,38:89:99:1230,0,1502 0/0:35,0:35:78:0,78,1170 0/0:31,0:31:72:0,72,1080 0/1:37,36:73:99:1180,0,1066 0/1:19,36:55:99:1214,0,539 0/0:52,0:52:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:51,0:51:99:0,111,1665 0/0:59,0:59:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:41,0:41:90:0,90,1350 0/0:40,0:40:99:0,102,1530 0/1:27,34:61:99:1152,0,790 0/1:33,39:72:99:1395,0,905 0/1:62,43:105:99:1477,0,1790 0/1:42,46:88:99:1530,0,1149 0/0:42,0:42:99:0,99,1485 0/1:48,51:99:99:1763,0,1429 0/0:54,0:54:99:0,111,1665 0/0:56,0:56:99:0,120,1800 0/0:39,0:39:90:0,90,1350 0/0:39,0:39:96:0,96,1440 0/1:57,93:150:99:3519,0,1491 0/0:57,0:57:99:0,120,1800 0/0:39,0:39:77:0,77,1305 0/0:40,0:40:99:0,99,1485 0/0:29,0:29:69:0,69,1035 0/0:25,0:25:61:0,61,990 0/0:55,0:55:99:0,117,1755 0/0:32,0:32:76:0,76,1260 0/1:66,48:114:99:1721,0,1839 0/0:30,0:30:72:0,72,1080 0/0:62,0:62:99:0,120,1800 0/1:40,31:71:99:1118,0,1225 0/0:32,0:32:69:0,69,1035 0/0:31,0:31:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:25,0:25:66:0,66,990 0/0:28,0:28:60:0,60,900 0/1:24,35:59:99:1273,0,653 0/0:38,0:38:84:0,84,1260 0/0:24,0:24:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:75:0,75,1125 0/0:65,0:65:99:0,120,1800 0/1:14,25:39:99:935,0,392 0/1:17,21:38:99:739,0,513 0/1:22,31:53:99:977,0,665 0/0:64,0:64:99:0,120,1800 0/1:17,20:37:99:713,0,471 0/0:27,0:27:60:0,60,900 1/1:0,70:70:99:3006,211,0 0/0:25,0:25:60:0,60,900 0/1:21,13:34:99:408,0,651 1/1:0,23:23:69:927,69,0 1/1:0,53:53:99:2243,160,0 0/0:26,0:26:60:0,60,900 0/1:30,26:56:99:954,0,886 1/1:0,76:76:99:3203,229,0 +20 13755926 . GAGA G 3920.69 PASS HWP=1.0;AC=2;culprit=MQRankSum;MQ0=0;ReadPosRankSum=1.02;AN=200;InbreedingCoeff=-0.0017;AF=0.001724;GQ_STDDEV=80.16;FS=2.807;DP=26703;GQ_MEAN=81.47;POSITIVE_TRAIN_SITE;VQSLOD=3.75;ClippingRankSum=0.32;BaseQRankSum=0.753;MLEAF=0.001724;MLEAC=3;MQ=57.03;QD=16.34;MQRankSum=-1.482;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:90:0,90,1091 0/0:37,0:37:78:0,78,1170 0/0:27,0:27:66:0,66,909 0/0:37,0:37:99:0,105,1446 0/0:35,0:35:99:0,99,1456 0/0:37,0:37:93:0,93,1294 0/0:50,0:50:77:0,77,1665 0/0:25,0:25:72:0,72,1080 0/0:28,0:28:69:0,69,1035 0/0:32,0:32:87:0,87,1280 0/0:41,0:41:99:0,120,1800 0/0:22,0:22:61:0,61,945 0/0:35,0:35:75:0,75,1125 0/0:36,0:36:72:0,72,1080 0/0:34,0:34:71:0,71,1170 0/0:25,0:25:63:0,63,932 0/1:38,38:76:99:1474,0,1758 0/0:24,0:24:69:0,69,1035 0/0:24,0:24:69:0,69,1035 0/0:26,0:26:65:0,65,907 0/0:26,0:26:72:0,72,917 0/0:32,0:32:90:0,90,1350 0/0:31,0:31:69:0,69,1035 0/0:20,0:20:60:0,60,756 0/0:21,0:21:63:0,63,799 0/0:47,0:47:99:0,111,1665 0/0:38,0:38:99:0,105,1575 0/0:26,0:26:75:0,75,1125 0/0:32,0:32:96:0,96,1137 0/0:31,0:31:66:0,66,1075 0/0:21,0:21:60:0,60,768 0/0:30,0:30:81:0,81,1215 0/0:66,0:66:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:41,0:41:99:0,111,1665 0/1:35,22:57:99:815,0,1626 0/0:21,0:21:63:0,63,752 0/0:27,0:27:62:0,62,882 0/0:35,0:35:93:0,93,1395 0/0:39,0:39:99:0,99,1485 0/0:23,0:23:63:0,63,843 0/0:35,0:35:91:0,91,1247 0/0:24,0:24:60:0,60,900 0/0:28,0:28:67:0,67,1080 0/0:28,0:28:84:0,84,1009 0/0:37,0:37:99:0,110,1356 0/0:27,0:27:63:0,63,1035 0/0:38,0:38:99:0,108,1620 0/0:43,0:43:99:0,118,1800 0/0:55,0:55:99:0,120,1800 0/0:23,0:23:66:0,66,934 0/0:32,0:32:82:0,82,1089 0/0:28,0:28:60:0,60,900 0/0:20,0:20:60:0,60,696 0/0:39,0:39:99:0,117,1414 0/0:41,0:41:99:0,117,1755 0/0:28,0:28:78:0,78,1170 0/0:46,0:46:99:0,120,1800 0/0:37,0:37:99:0,111,1315 0/0:48,0:48:99:0,120,1651 0/0:23,0:23:63:0,63,945 0/0:37,0:37:93:0,93,1395 0/0:68,0:68:99:0,120,1800 0/0:33,0:33:92:0,92,1194 0/0:31,0:31:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,895 0/0:23,0:23:62:0,62,889 0/0:47,0:47:99:0,120,1800 0/0:25,0:25:60:0,60,900 0/0:50,0:50:99:0,120,1800 0/0:25,0:25:69:0,69,1035 0/0:47,0:47:99:0,120,1800 0/0:20,0:20:60:0,60,702 0/0:26,0:26:78:0,78,935 0/0:22,0:22:60:0,60,900 0/0:33,0:33:99:0,99,1196 0/0:30,0:30:75:0,75,1125 0/0:25,0:25:60:0,60,894 0/0:37,0:37:99:0,108,1620 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,734 0/0:33,0:33:81:0,81,1215 0/0:34,0:34:99:0,99,1211 0/0:42,0:42:99:0,120,1800 0/0:25,0:25:66:0,66,903 0/0:26,0:26:62:0,62,945 0/0:36,0:36:81:0,81,1215 0/0:47,0:47:99:0,120,1800 0/0:22,0:22:63:0,63,772 0/0:22,0:22:63:0,63,945 0/0:28,0:28:69:0,69,1035 0/0:28,0:28:81:0,81,1215 0/0:24,0:24:62:0,62,889 0/0:23,0:23:60:0,60,855 0/0:21,0:21:60:0,60,710 0/0:28,0:28:84:0,84,985 0/0:36,0:36:71:0,71,1080 0/0:30,0:30:90:0,90,1065 +20 13763601 rs6131521 A G 24647.20 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.392;AN=200;InbreedingCoeff=-0.0099;AF=0.00977;GQ_STDDEV=197.65;FS=0.0;DP=24487;GQ_MEAN=91.26;POSITIVE_TRAIN_SITE;VQSLOD=6.56;ClippingRankSum=-0.415;BaseQRankSum=5.56;MLEAF=0.00977;MLEAC=17;MQ=59.68;QD=14.69;DB;MQRankSum=0.16;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,869 0/0:22,0:22:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,736 0/0:21,0:21:60:0,60,860 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:39,0:39:96:0,96,1440 0/0:30,0:30:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:48,0:48:99:0,99,1485 0/0:28,0:28:60:0,60,900 0/0:36,0:36:78:0,78,1170 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:32,0:32:81:0,81,1215 0/0:29,0:29:64:0,64,1073 0/0:32,0:32:69:0,69,1035 0/0:28,0:28:64:0,64,1035 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,793 0/0:38,0:38:69:0,69,1485 0/0:32,0:32:76:0,76,1215 0/0:39,0:39:99:0,99,1485 0/0:22,0:22:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:40,0:40:93:0,93,1395 0/0:23,0:23:60:0,60,900 0/0:44,0:44:93:0,93,1395 0/0:27,0:27:62:0,62,945 0/0:26,0:26:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:32,0:32:76:0,76,1215 0/0:30,0:30:63:0,63,945 0/0:40,0:40:99:0,102,1448 0/0:29,0:29:66:0,66,990 0/0:34,0:34:75:0,75,1125 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,775 0/0:29,0:29:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:27,0:27:69:0,69,1035 0/0:40,0:40:96:0,96,1440 0/0:32,0:32:66:0,66,990 0/0:34,0:34:75:0,75,1125 0/0:23,0:23:60:0,60,819 0/0:27,0:27:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:30,0:30:74:0,74,1090 0/0:26,0:26:60:0,60,900 0/0:43,0:43:99:0,114,1710 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:36,0:36:90:0,90,1350 0/0:21,0:21:60:0,60,900 0/0:44,0:44:99:0,100,1575 0/0:23,0:23:60:0,60,900 0/0:29,0:29:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,931 0/0:25,0:25:63:0,63,933 0/0:26,0:26:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,884 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,838 0/0:30,0:30:65:0,65,1125 0/0:21,0:21:60:0,60,900 0/0:40,0:40:93:0,93,1395 0/0:22,0:22:63:0,63,856 0/0:23,0:23:60:0,60,900 0/0:43,0:43:93:0,93,1395 0/1:60,43:103:99:1481,0,1577 0/0:20,0:20:60:0,60,683 0/0:20,0:20:60:0,60,801 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,756 0/0:25,0:25:60:0,60,900 0/1:34,25:59:99:833,0,978 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 +20 13765652 rs189011890 G A 45.94 PASS NEGATIVE_TRAIN_SITE;HWP=1.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=0.248;AN=192;InbreedingCoeff=-0.0476;AF=5.995E-4;GQ_STDDEV=9.89;FS=3.01;DP=4454;GQ_MEAN=14.93;VQSLOD=-1.196;ClippingRankSum=0.573;BaseQRankSum=1.0;MLEAF=5.995E-4;MLEAC=1;MQ=60.0;QD=5.1;DB;MQRankSum=-1.001;CCC=1668;NCC=36 GT:AD:DP:GQ:PL 0/0:7,0:7:21:0,21,257 0/0:9,0:9:24:0,24,334 0/0:8,0:8:21:0,21,315 0/0:9,0:9:24:0,24,322 0/0:3,0:3:9:0,9,114 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,245 0/0:8,0:8:24:0,24,317 0/0:7,0:7:21:0,21,237 0/0:9,0:9:27:0,27,329 0/0:2,0:2:6:0,6,71 0/0:5,0:5:6:0,6,90 0/0:7,0:7:21:0,21,241 0/0:8,0:8:21:0,21,295 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,77 0/0:10,0:10:27:0,27,351 0/0:5,0:5:12:0,12,169 0/0:4,0:4:9:0,9,135 0/0:2,0:2:6:0,6,71 0/0:3,0:3:9:0,9,113 0/0:3,0:3:9:0,9,99 0/0:2,0:2:6:0,6,51 ./.:0,0:0:.:. 0/0:2,0:2:3:0,3,45 0/0:7,0:7:21:0,21,263 0/0:2,0:2:6:0,6,75 0/0:8,0:8:21:0,21,288 0/0:7,0:7:21:0,21,242 0/0:7,0:7:21:0,21,234 0/0:7,0:7:21:0,21,238 0/0:2,0:2:6:0,6,67 0/0:3,0:3:6:0,6,90 0/0:7,0:7:21:0,21,271 0/0:9,0:9:21:0,21,315 ./.:0,0:0:.:. 0/0:3,0:3:9:0,9,120 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,74 0/0:7,0:7:21:0,21,241 0/0:3,0:3:6:0,6,83 0/0:7,0:7:21:0,21,241 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,65 0/1:6,3:9:95:95,0,205 0/0:11,0:11:22:0,22,358 0/0:2,0:2:6:0,6,75 0/0:8,0:8:24:0,24,292 0/0:6,0:6:15:0,15,221 0/0:8,0:8:21:0,21,315 0/0:5,0:5:15:0,15,185 0/0:5,0:5:15:0,15,200 0/0:2,0:2:6:0,6,72 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,65 0/0:2,0:2:6:0,6,73 0/0:7,0:7:21:0,21,259 0/0:7,0:7:21:0,21,256 0/0:7,0:7:21:0,21,262 0/0:7,0:7:21:0,21,261 0/0:7,0:7:21:0,21,262 0/0:4,0:4:12:0,12,112 0/0:10,0:10:30:0,30,376 0/0:3,0:3:9:0,9,104 0/0:2,0:2:6:0,6,61 0/0:1,0:1:3:0,3,37 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,69 0/0:8,0:8:21:0,21,315 0/0:2,0:2:6:0,6,71 0/0:2,0:2:6:0,6,56 0/0:2,0:2:6:0,6,75 0/0:3,0:3:9:0,9,115 0/0:1,0:1:3:0,3,30 0/0:1,0:1:3:0,3,16 ./.:0,0:0:.:. 0/0:1,0:1:3:0,3,12 0/0:1,0:1:3:0,3,32 0/0:2,0:2:6:0,6,72 0/0:2,0:2:6:0,6,69 0/0:2,0:2:6:0,6,72 0/0:2,0:2:6:0,6,58 0/0:2,0:2:6:0,6,61 0/0:2,0:2:6:0,6,70 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,73 0/0:5,0:5:12:0,12,170 0/0:2,0:2:6:0,6,69 0/0:7,0:7:18:0,18,270 0/0:11,0:11:22:0,22,395 0/0:4,0:4:9:0,9,135 0/0:2,0:2:6:0,6,68 0/0:2,0:2:6:0,6,76 0/0:2,0:2:6:0,6,70 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,74 0/0:3,0:3:9:0,9,109 0/0:2,0:2:6:0,6,74 0/0:1,0:1:3:0,3,28 0/0:7,0:7:21:0,21,234 +20 13765942 rs139224057 CCCGCGGGG C 48748.90 PASS HWP=0.0068;AC=32;culprit=FS;MQ0=0;ReadPosRankSum=0.103;AN=178;InbreedingCoeff=0.0446;AF=0.107;GQ_STDDEV=106.48;FS=0.98;DP=10811;GQ_MEAN=63.02;POSITIVE_TRAIN_SITE;VQSLOD=2.15;ClippingRankSum=0.077;BaseQRankSum=0.38;MLEAF=0.113;MLEAC=189;MQ=55.82;QD=7.08;DB;MQRankSum=-0.411;CCC=1680;NCC=30 GT:AD:DP:GQ:PL 0/1:5,3:8:99:114,0,431 0/0:13,0:13:21:0,21,315 ./.:4,0:4:.:. 0/0:16,0:16:21:0,21,315 0/1:7,4:11:99:149,0,500 0/0:14,0:14:27:0,27,405 0/1:10,6:16:99:203,0,710 0/0:9,0:9:24:0,24,337 0/1:15,12:27:99:362,0,929 0/0:5,0:5:9:0,9,135 0/1:6,5:11:99:186,0,313 0/0:11,0:11:21:0,21,315 0/1:5,8:13:99:314,0,270 0/0:15,0:15:27:0,27,405 0/0:8,0:8:21:0,21,315 0/1:7,8:15:99:318,0,361 0/0:9,0:9:21:0,21,315 0/0:11,0:11:27:0,27,405 0/1:8,5:13:99:163,0,528 0/0:22,0:22:60:0,60,900 0/0:12,0:12:24:0,24,360 0/0:5,0:5:6:0,6,90 0/0:10,0:10:21:0,21,315 ./.:3,0:3:.:. 1/1:0,10:10:33:437,33,0 0/0:8,0:8:21:0,21,315 0/1:3,6:9:99:239,0,194 1/1:0,8:8:27:338,27,0 0/0:17,0:17:18:0,18,559 0/0:13,0:13:21:0,21,315 0/1:7,10:17:99:372,0,455 0/0:11,0:11:24:0,24,360 0/0:15,0:15:21:0,21,315 0/0:15,0:15:24:0,24,360 0/1:8,3:11:99:109,0,657 0/0:16,0:16:27:0,27,405 0/0:12,0:12:21:0,21,315 0/0:3,0:3:9:0,9,102 0/0:4,0:4:9:0,9,127 0/0:14,0:14:30:0,30,450 0/0:10,0:10:27:0,27,350 0/0:2,0:2:6:0,6,64 0/0:2,0:2:6:0,6,39 0/1:2,3:5:99:111,0,195 0/0:3,0:3:6:0,6,90 0/1:3,6:9:99:242,0,133 0/1:5,2:7:66:66,0,404 0/0:2,0:2:6:0,6,67 0/0:5,0:5:9:0,9,135 0/1:5,2:7:60:60,0,209 0/0:6,0:6:9:0,9,135 0/0:8,0:8:0:0,0,208 0/0:11,0:11:27:0,27,405 0/0:7,0:7:6:0,6,90 0/0:8,0:8:21:0,21,259 ./.:1,0:1:.:. 1/1:0,13:13:41:510,41,0 0/0:13,0:13:30:0,30,450 0/0:9,0:9:9:0,9,135 0/1:5,5:10:99:188,0,288 ./.:0,0:0:.:. 0/0:5,0:5:6:0,6,90 0/0:21,0:21:39:0,39,585 ./.:6,0:6:.:. 0/0:3,0:3:6:0,6,90 0/1:8,3:11:91:91,0,504 1/1:0,3:3:10:121,10,0 0/0:3,0:3:9:0,9,85 0/1:11,3:14:93:93,0,412 1/1:0,6:6:21:233,21,0 0/0:9,0:9:18:0,18,270 0/0:7,0:7:21:0,21,258 ./.:5,0:5:.:. 0/0:4,0:4:6:0,6,90 0/1:3,4:7:83:150,0,83 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:3,0:3:0:0,0,38 ./.:3,0:3:.:. 1/1:0,9:9:29:379,29,0 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,66 ./.:2,0:2:.:. 0/0:6,0:6:12:0,12,180 0/1:3,8:11:79:307,0,79 0/0:18,0:18:27:0,27,405 0/0:11,0:11:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:15,0:15:32:0,32,585 0/0:18,0:18:36:0,36,540 0/0:12,0:12:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:15,0:15:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:7,0:7:21:0,21,266 ./.:1,0:1:.:. 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,87 +20 13765944 . C G 1848.78 VQSRTrancheINDEL97.00to99.00 HWP=1.0;AC=2;culprit=QD;MQ0=0;ReadPosRankSum=-0.248;AN=134;InbreedingCoeff=0.073;AF=0.00431;GQ_STDDEV=25.87;FS=6.846;DP=7983;GQ_MEAN=25.26;VQSLOD=-0.2581;ClippingRankSum=0.55;BaseQRankSum=0.572;MLEAF=0.00431;MLEAC=6;MQ=56.02;QD=4.47;MQRankSum=-0.72;CCC=1392;NCC=174 GT:AD:DP:GQ:PL ./.:0,0:.:.:. 0/0:13,0:13:21:0,21,315 ./.:4,0:4:.:. 0/0:6,0:6:6:0,6,90 ./.:0,0:.:.:. 0/0:14,0:14:27:0,27,405 ./.:0,0:.:.:. 0/0:9,0:9:24:0,24,337 ./.:0,0:.:.:. 0/0:5,0:5:3:0,3,45 ./.:0,0:.:.:. 0/0:11,0:11:21:0,21,315 ./.:0,0:.:.:. 0/0:15,0:15:27:0,27,405 0/0:8,0:8:21:0,21,315 ./.:0,0:.:.:. 0/0:6,0:6:12:0,12,180 0/0:11,0:11:27:0,27,405 ./.:0,0:.:.:. 0/0:22,0:22:60:0,60,900 0/0:12,0:12:24:0,24,360 0/0:5,0:5:6:0,6,90 0/0:10,0:10:21:0,21,315 ./.:3,0:3:.:. ./.:0,0:.:.:. 0/0:8,0:8:21:0,21,315 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:15,0:15:21:0,21,315 0/0:13,0:13:21:0,21,315 ./.:0,0:.:.:. 0/0:11,0:11:24:0,24,360 0/0:15,0:15:21:0,21,315 0/0:15,0:15:24:0,24,360 0/0:11,0:11:40:0,40,578 0/0:16,0:16:27:0,27,405 0/0:12,0:12:21:0,21,315 0/0:3,0:3:9:0,9,102 0/0:5,0:5:0:0,0,100 0/0:14,0:14:30:0,30,450 0/0:10,0:10:27:0,27,350 0/0:2,0:2:6:0,6,64 0/0:2,0:2:6:0,6,39 ./.:0,0:.:.:. 0/0:3,0:3:6:0,6,90 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:2,0:2:6:0,6,67 0/0:5,0:5:9:0,9,135 0/0:5,0:5:18:0,18,235 0/0:6,0:6:9:0,9,135 0/1:2,4:6:49:125,0,49 0/0:11,0:11:27:0,27,405 0/0:7,0:7:6:0,6,90 0/0:8,0:8:21:0,21,259 ./.:1,0:1:.:. ./.:0,0:.:.:. 0/0:13,0:13:30:0,30,450 0/0:9,0:9:9:0,9,135 ./.:0,0:.:.:. ./.:0,0:0:.:. 0/0:4,0:4:0:0,0,45 0/0:21,0:21:39:0,39,585 ./.:6,0:6:.:. 0/0:3,0:3:6:0,6,90 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:3,0:3:9:0,9,85 ./.:0,0:.:.:. ./.:0,0:.:.:. 0/0:4,0:4:6:0,6,90 0/0:7,0:7:21:0,21,258 0/1:2,3:5:58:107,0,58 0/0:4,0:4:6:0,6,90 ./.:0,0:.:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:3,0:3:0:0,0,38 ./.:3,0:3:.:. ./.:0,0:.:.:. 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,66 ./.:2,0:2:.:. 0/0:6,0:6:12:0,12,180 0/0:3,0:11:9:0,9,115 0/0:18,0:18:27:0,27,405 0/0:11,0:11:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:15,0:15:4:0,4,377 0/0:18,0:18:36:0,36,540 0/0:12,0:12:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:15,0:15:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:5,0:5:6:0,6,90 ./.:1,0:1:.:. 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,87 +20 13765954 rs113805278 C T 2490.29 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.0;AN=182;InbreedingCoeff=-0.0474;AF=0.008516;GQ_STDDEV=21.97;FS=2.45;DP=7226;GQ_MEAN=20.09;VQSLOD=3.11;ClippingRankSum=0.702;BaseQRankSum=1.79;MLEAF=0.009124;MLEAC=15;MQ=60.0;QD=13.46;DB;MQRankSum=0.322;CCC=1644;NCC=48 GT:AD:DP:GQ:PL 0/0:5,0:5:6:0,6,90 0/0:2,0:2:6:0,6,75 0/0:2,0:2:6:0,6,70 0/0:6,0:6:6:0,6,90 0/0:8,0:8:21:0,21,315 0/0:6,0:6:9:0,9,135 0/0:4,0:4:9:0,9,135 0/0:5,0:5:12:0,12,174 0/0:8,0:8:21:0,21,305 0/0:2,0:2:6:0,6,43 0/0:6,0:6:15:0,15,225 0/0:3,0:3:6:0,6,90 0/0:9,0:9:24:0,24,360 0/0:2,0:2:6:0,6,80 0/0:8,0:8:21:0,21,315 0/0:10,0:10:21:0,21,315 0/1:3,3:6:88:93,0,88 0/0:8,0:8:15:0,15,225 0/0:3,0:3:6:0,6,90 0/0:10,0:10:21:0,21,315 0/0:12,0:12:24:0,24,360 0/0:5,0:5:6:0,6,90 0/0:5,0:5:9:0,9,135 0/0:3,0:3:6:0,6,85 0/0:5,0:5:12:0,12,180 0/0:7,0:7:21:0,21,260 0/0:7,0:7:12:0,12,180 0/0:5,0:5:12:0,12,140 0/0:9,0:9:9:0,9,135 0/0:13,0:13:21:0,21,315 0/0:15,0:15:9:0,9,434 0/0:11,0:11:24:0,24,360 0/0:14,0:14:28:0,28,450 0/0:3,0:3:9:0,9,99 0/0:10,0:10:21:0,21,315 0/1:4,6:10:99:201,0,122 0/0:12,0:12:21:0,21,315 0/0:3,0:3:9:0,9,102 0/0:2,0:2:6:0,6,60 0/0:4,0:4:9:0,9,135 0/0:6,0:6:9:0,9,135 0/0:2,0:2:6:0,6,64 0/0:1,0:1:3:0,3,40 0/0:4,0:4:9:0,9,128 0/0:3,0:3:6:0,6,90 0/0:7,0:7:12:0,12,180 0/0:5,0:5:9:0,9,135 0/0:2,0:2:6:0,6,67 ./.:1,0:1:.:. 0/0:5,0:5:9:0,9,135 0/0:6,0:6:9:0,9,135 0/0:4,0:4:6:0,6,90 0/0:3,0:3:6:0,6,90 ./.:1,0:1:.:. 0/0:8,0:8:21:0,21,259 0/0:2,0:2:6:0,6,50 0/0:4,0:4:9:0,9,135 0/0:12,0:12:12:0,12,180 0/0:4,0:4:3:0,3,45 0/0:7,0:7:6:0,6,90 ./.:0,0:0:.:. 0/0:3,0:3:6:0,6,83 0/0:11,0:11:21:0,21,315 0/0:6,0:6:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:5,0:5:12:0,12,177 0/0:2,0:2:6:0,6,75 0/0:3,0:3:9:0,9,85 0/0:4,0:4:9:0,9,135 0/0:5,0:5:9:0,9,135 0/0:4,0:4:6:0,6,90 0/0:5,0:5:6:0,6,90 ./.:0,0:0:.:. 0/0:4,0:4:6:0,6,90 ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:3,0:3:0:0,0,38 0/0:2,0:2:6:0,6,66 0/0:5,0:5:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,66 ./.:2,0:2:.:. 0/0:2,0:2:3:0,3,45 0/0:6,0:6:12:0,12,180 0/0:18,0:18:27:0,27,405 0/0:11,0:11:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:3,0:3:9:0,9,118 0/0:12,0:12:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:1,0:1:3:0,3,31 0/0:15,0:15:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:5,0:5:6:0,6,90 ./.:1,0:1:.:. 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,87 +20 13767943 rs74421815 C T 119641.00 PASS HWP=0.0015;AC=9;culprit=FS;MQ0=0;ReadPosRankSum=0.424;AN=200;InbreedingCoeff=0.153;AF=0.037;GQ_STDDEV=440.86;FS=0.0;DP=66607;GQ_MEAN=206.65;POSITIVE_TRAIN_SITE;VQSLOD=5.73;ClippingRankSum=-0.081;BaseQRankSum=-1.768;MLEAF=0.037;MLEAC=65;MQ=59.54;QD=14.32;DB;MQRankSum=0.24;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:83,0:83:99:0,120,1800 0/0:55,0:55:99:0,114,1710 0/0:65,0:65:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:57,0:57:99:0,117,1755 0/0:72,0:72:99:0,120,1800 0/0:45,0:45:99:0,111,1665 0/0:79,0:79:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:57,0:57:99:0,111,1665 0/0:53,0:53:99:0,114,1710 0/0:77,0:77:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:28,0:28:69:0,69,1035 0/0:46,0:46:99:0,108,1620 0/1:44,29:73:99:822,0,1357 0/0:58,0:58:99:0,120,1800 0/0:39,0:39:99:0,105,1341 0/0:50,0:50:99:0,114,1710 0/0:45,0:45:99:0,102,1530 0/1:64,58:122:99:1503,0,1731 0/0:46,0:46:99:0,102,1530 0/0:118,0:118:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:41,0:41:96:0,96,1440 0/0:33,0:33:72:0,72,1080 0/0:38,0:38:99:0,99,1485 0/0:141,0:141:99:0,120,1800 0/0:150,0:150:99:0,120,1800 0/0:134,0:134:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/1:69,64:133:99:1813,0,2164 0/0:65,0:65:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/1:118,101:219:99:2341,0,3211 0/0:74,0:74:99:0,120,1800 0/0:36,0:36:66:0,66,990 0/0:37,0:37:84:0,84,1260 0/0:54,0:54:99:0,120,1800 0/0:30,0:30:74:0,74,1170 0/0:32,0:32:75:0,75,1125 0/0:45,0:45:99:0,120,1800 0/0:46,0:46:99:0,105,1575 0/1:31,35:66:99:1003,0,882 0/0:46,0:46:96:0,96,1440 0/0:48,0:48:99:0,108,1620 0/0:47,0:47:99:0,111,1665 0/1:120,100:220:99:2859,0,3761 0/0:130,0:130:99:0,120,1800 0/0:30,0:30:75:0,75,1125 0/0:26,0:26:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:30,0:30:69:0,69,1035 0/1:46,61:107:99:1628,0,1343 0/0:37,0:37:84:0,84,1260 0/0:52,0:52:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:45,0:45:99:0,104,1620 0/0:121,0:121:99:0,120,1800 0/0:29,0:29:72:0,72,1071 0/0:31,0:31:75:0,75,1125 0/0:69,0:69:99:0,120,1800 0/0:42,0:42:90:0,90,1350 0/0:37,0:37:80:0,80,1215 0/0:44,0:44:99:0,105,1575 0/0:29,0:29:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:116,0:116:99:0,120,1800 0/0:38,0:38:95:0,95,1575 0/0:63,0:63:99:0,120,1800 0/0:27,0:27:66:0,66,990 0/0:73,0:73:99:0,120,1800 0/0:30,0:30:66:0,66,990 0/1:42,41:83:99:1105,0,1215 0/1:28,21:49:99:617,0,937 0/0:37,0:37:93:0,93,1395 0/0:30,0:30:72:0,72,1080 0/0:35,0:35:84:0,84,1260 0/0:46,0:46:99:0,102,1530 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:63:0,63,941 0/0:41,0:41:87:0,87,1305 0/0:31,0:31:60:0,60,900 0/0:57,0:57:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:42,0:42:96:0,96,1440 0/0:29,0:29:66:0,66,990 0/0:74,0:74:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:51,0:51:99:0,114,1710 +20 13779113 rs2273317 T C 71559.00 PASS HWP=0.0448;AC=11;culprit=FS;MQ0=0;ReadPosRankSum=0.839;AN=200;InbreedingCoeff=0.0942;AF=0.036;GQ_STDDEV=253.39;FS=0.0;DP=31332;GQ_MEAN=131.91;POSITIVE_TRAIN_SITE;VQSLOD=6.43;ClippingRankSum=-0.18;BaseQRankSum=2.43;MLEAF=0.036;MLEAC=63;MQ=59.63;QD=15.38;DB;MQRankSum=0.047;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:36,0:36:78:0,78,1170 0/1:40,21:61:99:598,0,1047 0/0:21,0:21:60:0,60,869 0/0:27,0:27:69:0,69,1035 0/0:25,0:25:66:0,66,945 0/0:34,0:34:93:0,93,1395 0/0:29,0:29:62:0,62,990 0/1:16,30:46:99:854,0,426 0/0:30,0:30:75:0,75,1125 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:30,0:30:78:0,78,1260 0/0:26,0:26:69:0,69,1035 0/0:21,0:21:60:0,60,771 0/0:35,0:35:75:0,75,1125 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:93:0,93,1395 0/0:31,0:31:75:0,75,1125 0/0:30,0:30:84:0,84,1260 0/0:36,0:36:90:0,90,1350 0/0:56,0:56:99:0,105,1575 0/0:46,0:46:93:0,93,1395 0/0:42,0:42:90:0,90,1350 0/0:49,0:49:99:0,99,1485 0/0:30,0:30:63:0,63,945 0/0:41,0:41:87:0,87,1305 0/1:36,35:71:99:989,0,1023 0/0:28,0:28:69:0,69,946 0/0:28,0:28:60:0,60,900 0/0:79,0:79:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:36,0:36:81:0,81,1215 0/0:34,0:34:84:0,84,1260 0/0:50,0:50:99:0,120,1800 0/0:24,0:24:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:34,0:34:96:0,96,1440 0/0:35,0:35:87:0,87,1305 0/0:38,0:38:90:0,90,1350 0/0:47,0:47:99:0,120,1800 0/0:43,0:43:99:0,102,1530 0/0:44,0:44:99:0,114,1710 0/0:59,0:59:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:44,0:44:99:0,110,1665 0/0:29,0:29:72:0,72,1080 0/0:27,0:27:63:0,63,945 0/0:28,0:28:65:0,65,1080 0/0:54,0:54:99:0,114,1710 0/0:47,0:47:99:0,120,1800 0/0:42,0:42:87:0,87,1305 0/0:43,0:43:99:0,105,1575 0/0:55,0:55:99:0,114,1710 0/0:64,0:64:99:0,120,1800 0/0:36,0:36:84:0,84,1260 0/0:30,0:30:79:0,79,1215 0/0:78,0:78:99:0,120,1800 0/0:31,0:31:63:0,63,945 0/0:38,0:38:81:0,81,1215 0/0:38,0:38:78:0,78,1170 0/0:20,0:20:60:0,60,743 0/0:21,0:21:60:0,60,778 0/0:50,0:50:99:0,120,1800 0/0:25,0:25:75:0,75,920 0/0:57,0:57:99:0,120,1800 0/0:49,0:49:99:0,114,1710 0/0:65,0:65:99:0,120,1800 0/0:28,0:28:72:0,72,1080 0/0:35,0:35:96:0,96,1440 0/0:22,0:22:60:0,60,900 0/0:39,0:39:81:0,81,1289 0/0:23,0:23:66:0,66,990 0/0:39,0:39:96:0,96,1440 0/0:44,0:44:99:0,120,1800 0/0:26,0:26:62:0,62,945 0/0:25,0:25:63:0,63,945 0/0:34,0:34:72:0,72,1080 0/0:38,0:38:96:0,96,1393 0/0:48,0:48:99:0,99,1485 0/0:49,0:49:90:0,90,1350 0/0:25,0:25:63:0,63,945 0/1:24,33:57:99:874,0,598 0/1:32,33:65:99:958,0,831 0/0:48,0:48:99:0,99,1485 0/1:44,47:91:99:1142,0,1131 0/0:20,0:20:60:0,60,695 0/1:41,43:84:99:1245,0,1120 0/0:28,0:28:63:0,63,945 0/0:30,0:30:69:0,69,1035 1/1:0,61:61:99:1848,183,0 0/1:35,23:58:99:699,0,1047 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:41,33:74:99:1005,0,1258 +20 13782194 rs117002283 C T 8477.21 PASS HWP=1.0;AC=7;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.029;AN=200;InbreedingCoeff=-0.0083;AF=0.008046;GQ_STDDEV=74.61;FS=3.018;DP=18834;GQ_MEAN=67.92;POSITIVE_TRAIN_SITE;VQSLOD=4.2;ClippingRankSum=-0.065;BaseQRankSum=-1.549;MLEAF=0.008046;MLEAC=14;MQ=59.71;QD=13.27;DB;MQRankSum=0.132;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:63:0,63,873 0/0:20,0:20:60:0,60,746 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,775 0/0:22,0:22:63:0,63,760 0/0:20,0:20:60:0,60,724 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,816 0/0:25,0:25:69:0,69,923 0/0:28,0:28:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:23,0:23:63:0,63,914 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,714 0/0:21,0:21:60:0,60,869 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,690 0/0:20,0:20:60:0,60,746 0/0:20,0:20:60:0,60,755 0/0:22,0:22:63:0,63,779 0/0:20,0:20:60:0,60,692 0/1:47,26:73:99:732,0,1293 0/0:21,0:21:63:0,63,789 0/0:20,0:20:60:0,60,732 0/0:20,0:20:60:0,60,723 0/0:20,0:20:60:0,60,714 0/0:22,0:22:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:69:0,69,777 0/0:20,0:20:60:0,60,709 0/0:28,0:28:81:0,81,1163 0/0:20,0:20:60:0,60,738 0/1:36,35:71:99:997,0,1213 0/0:22,0:22:66:0,66,805 0/0:23,0:23:69:0,69,841 0/0:20,0:20:60:0,60,678 0/0:20,0:20:60:0,60,667 0/0:28,0:28:75:0,75,1060 0/0:20,0:20:60:0,60,721 0/0:20,0:20:60:0,60,792 0/0:20,0:20:60:0,60,685 0/0:20,0:20:60:0,60,725 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,815 0/1:21,25:46:99:753,0,563 0/0:20,0:20:60:0,60,726 0/0:21,0:21:63:0,63,788 0/0:20,0:20:60:0,60,687 0/1:35,29:64:99:845,0,1151 0/0:25,0:25:75:0,75,1008 0/0:20,0:20:60:0,60,725 0/0:20,0:20:60:0,60,725 0/0:23,0:23:66:0,66,802 0/0:20,0:20:60:0,60,736 0/1:19,20:39:99:620,0,648 0/0:20,0:20:60:0,60,716 0/0:20,0:20:60:0,60,762 0/0:21,0:21:60:0,60,765 0/0:21,0:21:60:0,60,900 0/0:32,0:32:87:0,87,1146 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,719 0/0:20,0:20:60:0,60,768 0/0:21,0:21:63:0,63,760 0/0:20,0:20:60:0,60,704 0/0:23,0:23:63:0,63,874 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,873 0/0:21,0:21:60:0,60,794 0/0:27,0:27:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:22,0:22:63:0,63,941 0/0:20,0:20:60:0,60,740 0/0:32,0:32:69:0,69,1035 0/1:17,19:36:99:544,0,556 0/1:23,16:39:99:439,0,765 0/0:28,0:28:60:0,60,934 0/0:21,0:21:60:0,60,774 0/0:28,0:28:72:0,72,1080 0/0:21,0:21:60:0,60,810 0/0:21,0:21:60:0,60,758 0/0:21,0:21:60:0,60,804 0/0:27,0:27:72:0,72,1080 0/0:20,0:20:60:0,60,731 0/0:22,0:22:60:0,60,805 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,651 0/0:21,0:21:60:0,60,719 0/0:20,0:20:60:0,60,759 0/0:22,0:22:66:0,66,777 0/0:27,0:27:66:0,66,990 0/0:21,0:21:60:0,60,728 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,901 0/0:20,0:20:60:0,60,772 0/0:20,0:20:60:0,60,758 0/0:20,0:20:60:0,60,699 0/0:19,0:19:51:0,51,765 0/0:28,0:28:60:0,60,900 +20 13797214 . A C 1532.70 VQSRTrancheSNP99.90to99.95 HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.253;AN=200;InbreedingCoeff=-0.0798;AF=0.015;GQ_STDDEV=27.66;FS=66.854;DP=20341;GQ_MEAN=34.45;VQSLOD=-43.71;ClippingRankSum=0.407;BaseQRankSum=-2.365;MLEAF=0.018;MLEAC=32;MQ=59.28;QD=2.05;MQRankSum=-0.095;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:27,0:27:63:0,63,945 0/0:33,0:33:84:0,84,1145 0/0:33,0:33:20:0,20,730 0/0:25,0:25:69:0,69,987 0/0:23,0:23:66:0,66,935 0/0:39,0:39:51:0,51,1058 0/0:28,0:28:37:0,37,677 0/0:25,0:25:63:0,63,875 0/0:47,0:47:51:0,51,1288 0/0:26,0:26:60:0,60,900 0/0:24,0:24:72:0,72,959 0/0:27,0:27:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:24,0:24:61:0,61,778 0/0:23,0:23:46:0,46,608 0/0:29,0:29:22:0,22,717 0/0:14,0:14:27:0,27,405 0/0:12,0:12:18:0,18,331 0/0:22,0:22:60:0,60,568 0/0:18,0:18:19:0,19,435 0/0:33,0:33:48:0,48,720 0/0:22,0:22:60:0,60,746 0/0:25,0:25:60:0,60,900 0/0:55,0:55:0:0,0,1374 0/0:45,0:45:51:0,51,1305 0/0:23,0:23:21:0,21,586 0/0:20,0:20:0:0,0,307 0/0:23,0:23:0:0,0,505 0/0:18,0:18:9:0,9,441 0/0:15,0:15:0:0,0,356 0/0:25,0:25:0:0,0,497 0/0:30,0:30:78:0,78,1046 0/0:25,0:25:0:0,0,547 0/0:28,0:28:63:0,63,783 0/0:34,0:34:0:0,0,673 0/0:26,0:26:36:0,36,762 0/0:33,0:33:0:0,0,838 0/0:31,0:31:60:0,60,778 0/0:17,0:17:11:0,11,422 0/0:24,0:24:29:0,29,585 0/0:14,0:14:0:0,0,207 0/0:16,0:16:9:0,9,381 0/0:12,0:12:0:0,0,298 0/0:17,0:17:38:0,38,460 0/0:19,0:19:57:0,57,571 0/0:30,0:30:0:0,0,696 0/0:24,0:24:63:0,63,718 0/0:23,0:23:0:0,0,445 0/0:23,0:23:6:0,6,581 0/0:22,0:22:0:0,0,499 0/0:23,0:23:23:0,23,592 0/0:20,0:20:39:0,39,585 0/0:8,0:8:0:0,0,206 0/0:19,0:19:31:0,31,499 0/0:19,0:19:0:0,0,351 0/0:18,0:18:36:0,36,499 0/0:21,0:21:51:0,51,574 0/1:21,21:42:99:141,0,485 0/0:20,0:20:0:0,0,419 0/0:31,0:31:71:0,71,928 0/0:22,0:22:42:0,42,628 0/0:18,0:18:0:0,0,203 0/0:28,0:28:0:0,0,656 0/0:21,0:21:0:0,0,479 0/0:18,0:18:6:0,6,466 0/0:24,0:24:35:0,35,619 0/0:6,0:6:0:0,0,118 0/0:8,0:8:24:0,24,228 0/0:31,0:31:16:0,16,742 0/0:11,0:11:24:0,24,322 0/0:23,0:23:16:0,16,548 0/0:15,0:15:0:0,0,290 0/0:16,0:16:36:0,36,427 0/0:9,0:9:0:0,0,195 0/0:12,0:12:24:0,24,360 0/0:4,0:4:0:0,0,56 0/0:18,0:18:13:0,13,396 0/0:13,0:13:24:0,24,361 0/0:13,0:13:33:0,33,381 0/0:14,0:14:0:0,0,189 0/0:8,0:8:0:0,0,143 0/0:3,0:3:9:0,9,66 0/0:9,0:9:5:0,5,176 0/0:10,0:10:0:0,0,179 0/0:11,0:11:27:0,27,317 0/0:23,0:23:0:0,0,532 0/0:30,0:30:60:0,60,832 0/0:36,0:36:34:0,34,968 0/0:26,0:26:69:0,69,809 0/0:37,0:37:0:0,0,779 0/0:40,0:40:41:0,41,1080 0/0:28,0:28:34:0,34,772 0/0:9,0:9:0:0,0,158 0/0:11,0:11:15:0,15,253 0/0:40,0:40:37:0,37,1034 0/0:23,0:23:50:0,50,632 0/0:11,0:11:0:0,0,190 0/0:7,0:7:20:0,20,220 0/0:14,0:14:0:0,0,308 0/0:6,0:6:18:0,18,176 +20 13798676 rs2423751 C T 3406.25 PASS NEGATIVE_TRAIN_SITE;HWP=0.0;AC=11;culprit=MQ;MQ0=0;ReadPosRankSum=0.322;AN=34;InbreedingCoeff=0.2564;AF=0.219;GQ_STDDEV=15.22;FS=4.075;DP=384;GQ_MEAN=10.36;POSITIVE_TRAIN_SITE;VQSLOD=1.27;ClippingRankSum=0.358;BaseQRankSum=0.0;MLEAF=0.281;MLEAC=63;MQ=60.0;QD=25.61;DB;MQRankSum=-0.727;CCC=224;NCC=758 GT:AD:DP:GQ:PL ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,4:4:12:126,12,0 0/0:4,0:4:0:0,0,41 1/1:0,5:5:15:165,15,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,67 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 0/0:3,0:3:0:0,0,38 1/1:0,4:4:12:152,12,0 0/1:1,3:4:29:105,0,29 0/1:1,3:4:29:97,0,29 0/0:2,0:2:6:0,6,49 0/0:2,0:2:6:0,6,60 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:1,0:1:3:0,3,35 ./.:0,0:0:.:. 0/1:3,2:5:62:62,0,100 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,3:3:10:131,10,0 ./.:4,0:4:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 13798692 rs71334159 TAACCTGGGCACTGC T 1379.33 PASS HWP=2.0E-4;AC=4;culprit=FS;MQ0=0;ReadPosRankSum=0.727;AN=34;InbreedingCoeff=0.0554;AF=0.055;GQ_STDDEV=32.24;FS=0.0;DP=318;GQ_MEAN=12.28;VQSLOD=2.7;ClippingRankSum=-0.358;BaseQRankSum=0.762;MLEAF=0.063;MLEAC=16;MQ=41.51;QD=6.16;DB;MQRankSum=-1.231;CCC=254;NCC=743 GT:AD:DP:GQ:PL ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,66 0/0:4,0:4:9:0,9,119 1/1:0,4:4:13:182,13,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,67 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,58 ./.:0,0:0:.:. 0/0:3,0:3:6:0,6,90 0/0:1,0:1:3:0,3,22 0/0:2,0:2:6:0,6,49 0/0:2,0:2:6:0,6,60 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:1,0:1:3:0,3,35 ./.:0,0:0:.:. 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,2:2:7:92,7,0 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 13798776 rs2423752 T C 10572.00 PASS HWP=0.0;AC=20;culprit=MQ;MQ0=0;ReadPosRankSum=1.3;AN=24;InbreedingCoeff=0.3867;AF=0.859;GQ_STDDEV=10.72;FS=0.0;DP=502;GQ_MEAN=12.86;POSITIVE_TRAIN_SITE;VQSLOD=2.51;ClippingRankSum=-0.727;BaseQRankSum=-0.358;MLEAF=0.911;MLEAC=175;MQ=60.0;QD=30.29;DB;MQRankSum=0.406;CCC=192;NCC=774 GT:AD:DP:GQ:PL ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:4,0:4:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,3:3:9:109,9,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,6:6:18:192,18,0 ./.:1,0:1:.:. 1/1:0,3:3:9:108,9,0 ./.:2,0:2:.:. 1/1:0,5:5:15:172,15,0 ./.:0,0:0:.:. 1/1:0,4:4:12:116,12,0 1/1:0,4:4:12:113,12,0 1/1:0,3:3:9:115,9,0 0/0:2,0:2:6:0,6,61 ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. 1/1:0,3:3:9:115,9,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:2,0:2:.:. 1/1:0,3:3:9:117,9,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. 1/1:0,4:4:12:133,12,0 ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:4,0:4:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 13830102 rs2073289 C T 265592.00 PASS HWP=0.0381;AC=47;culprit=FS;MQ0=0;ReadPosRankSum=0.618;AN=200;InbreedingCoeff=0.0768;AF=0.14;GQ_STDDEV=415.95;FS=0.0;DP=49981;GQ_MEAN=299.47;POSITIVE_TRAIN_SITE;VQSLOD=6.87;ClippingRankSum=0.078;BaseQRankSum=0.119;MLEAF=0.14;MLEAC=243;MQ=59.7;QD=15.03;DB;MQRankSum=0.19;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:39,25:64:99:678,0,1097 0/1:52,27:79:99:760,0,1504 0/1:47,26:73:99:721,0,1350 0/0:69,0:69:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/1:41,27:68:99:725,0,1219 0/1:42,19:61:99:491,0,1207 0/1:38,35:73:99:1093,0,1132 0/0:49,0:49:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:41,0:41:99:0,103,1502 0/1:47,28:75:99:860,0,1445 0/0:52,0:52:99:0,120,1800 0/0:35,0:35:87:0,87,1305 0/1:39,29:68:99:785,0,1126 0/0:42,0:42:87:0,87,1305 0/0:68,0:68:99:0,120,1800 0/1:40,26:66:99:720,0,1197 0/0:65,0:65:99:0,120,1800 0/0:42,0:42:88:0,88,1358 0/0:64,0:64:99:0,120,1800 0/0:48,0:48:99:0,111,1665 0/1:74,59:133:99:1662,0,2141 1/1:0,115:115:99:4036,345,0 0/0:36,0:36:93:0,93,979 0/1:44,50:94:99:1542,0,1205 1/1:0,88:88:99:3057,264,0 0/0:70,0:70:99:0,120,1800 0/1:44,36:80:99:1030,0,1251 0/1:42,31:73:99:803,0,1229 0/0:61,0:61:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:157,0:157:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:41,0:41:90:0,90,1350 0/0:38,0:38:87:0,87,1305 0/0:33,0:33:81:0,81,1215 0/0:97,0:97:99:0,120,1800 0/0:35,0:35:72:0,72,1080 0/0:32,0:32:70:0,70,1251 0/0:27,0:27:60:0,60,900 0/1:46,38:84:99:1187,0,1383 0/0:44,0:44:99:0,99,1485 0/0:52,0:52:94:0,94,1543 0/1:53,35:88:99:1002,0,1648 0/0:35,0:35:84:0,84,1260 0/0:48,0:48:99:0,99,1485 0/1:64,50:114:99:1553,0,1916 0/0:69,0:69:99:0,120,1800 0/1:40,35:75:99:1089,0,1117 0/0:21,0:21:60:0,60,900 0/1:43,30:73:99:867,0,1287 0/0:46,0:46:99:0,99,1485 0/1:34,43:77:99:1228,0,920 0/1:40,35:75:99:1136,0,1226 0/0:48,0:48:99:0,117,1755 0/0:47,0:47:99:0,105,1575 0/1:63,38:101:99:1022,0,2082 0/0:40,0:40:87:0,87,1305 0/0:30,0:30:75:0,75,1125 0/0:57,0:57:99:0,99,1485 0/1:34,40:74:99:1265,0,996 0/0:37,0:37:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/1:25,27:52:99:815,0,772 0/1:25,28:53:99:719,0,851 0/1:54,51:105:99:1616,0,1693 1/1:0,45:45:99:1616,135,0 0/1:57,50:107:99:1500,0,1575 0/0:33,0:33:75:0,75,1125 0/1:70,50:120:99:1405,0,1997 0/0:29,0:29:60:0,60,900 1/1:0,49:49:99:1780,147,0 1/1:0,56:56:99:1899,168,0 0/0:27,0:27:60:0,60,900 1/1:0,64:64:99:2365,192,0 0/1:41,27:68:99:772,0,1207 1/1:0,76:76:99:2670,228,0 0/0:34,0:34:90:0,90,1350 0/1:26,20:46:99:552,0,776 0/0:26,0:26:66:0,66,990 1/1:0,92:92:99:3252,277,0 0/1:41,41:82:99:1256,0,1183 0/1:70,66:136:99:2055,0,1936 0/0:47,0:47:96:0,96,1440 0/0:55,0:55:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:62,0:62:99:0,120,1800 0/0:52,0:52:99:0,105,1575 0/0:26,0:26:69:0,69,1035 0/0:27,0:27:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:34,0:34:69:0,69,1035 +20 13830137 rs2073290 A C 327469.00 PASS HWP=0.0381;AC=47;culprit=FS;MQ0=0;ReadPosRankSum=0.339;AN=200;InbreedingCoeff=0.0768;AF=0.14;GQ_STDDEV=509.87;FS=0.529;DP=52212;GQ_MEAN=348.41;POSITIVE_TRAIN_SITE;VQSLOD=6.21;ClippingRankSum=0.177;BaseQRankSum=4.08;MLEAF=0.14;MLEAC=243;MQ=59.7;QD=16.44;DB;MQRankSum=0.21;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:41,30:71:99:883,0,1214 0/1:46,25:71:99:696,0,1424 0/1:49,29:78:99:792,0,1309 0/0:69,0:69:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/1:50,39:89:99:1288,0,1452 0/1:44,27:71:99:816,0,1205 0/1:41,35:76:99:1208,0,1193 0/0:49,0:49:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:41,0:41:99:0,103,1502 0/1:37,37:74:99:1205,0,1116 0/0:52,0:52:99:0,120,1800 0/0:35,0:35:87:0,87,1305 0/1:45,40:85:99:1182,0,1287 0/0:42,0:42:87:0,87,1305 0/0:68,0:68:99:0,120,1800 0/1:48,30:78:99:823,0,1445 0/0:65,0:65:99:0,120,1800 0/0:42,0:42:88:0,88,1358 0/0:64,0:64:99:0,120,1800 0/0:48,0:48:99:0,111,1665 0/1:108,81:189:99:2444,0,3194 1/1:0,170:170:99:6409,511,0 0/0:36,0:36:93:0,93,979 0/1:56,47:103:99:1500,0,1590 1/1:0,98:98:99:3609,295,0 0/0:70,0:70:99:0,120,1800 0/1:51,48:99:99:1555,0,1443 0/1:51,41:92:99:1168,0,1400 0/0:61,0:61:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:157,0:157:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:41,0:41:90:0,90,1350 0/0:38,0:38:87:0,87,1305 0/0:33,0:33:81:0,81,1215 0/0:97,0:97:99:0,120,1800 0/0:35,0:35:72:0,72,1080 0/0:32,0:32:70:0,70,1251 0/0:27,0:27:60:0,60,900 0/1:35,37:72:99:1161,0,1057 0/0:44,0:44:99:0,99,1485 0/0:52,0:52:94:0,94,1543 0/1:58,38:96:99:1125,0,1766 0/0:35,0:35:84:0,84,1260 0/0:48,0:48:99:0,99,1485 0/1:65,49:114:99:1693,0,2009 0/0:69,0:69:99:0,120,1800 0/1:40,36:76:99:1156,0,1081 0/0:21,0:21:60:0,60,900 0/1:46,37:83:99:1217,0,1301 0/0:46,0:46:99:0,99,1485 0/1:34,44:78:99:1338,0,985 0/1:42,35:77:99:1124,0,1378 0/0:48,0:48:99:0,117,1755 0/0:47,0:47:99:0,105,1575 0/1:61,48:109:99:1648,0,1982 0/0:40,0:40:87:0,87,1305 0/0:30,0:30:75:0,75,1125 0/0:57,0:57:99:0,99,1485 0/1:43,49:92:99:1636,0,1220 0/0:37,0:37:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/1:29,30:59:99:984,0,843 0/1:27,32:59:99:1001,0,786 0/1:60,52:112:99:1719,0,1815 1/1:0,55:55:99:2259,165,0 0/1:61,49:110:99:1564,0,1583 0/0:33,0:33:75:0,75,1125 0/1:66,46:112:99:1411,0,1787 0/0:29,0:29:60:0,60,900 1/1:0,56:56:99:2346,168,0 1/1:0,64:64:99:2385,192,0 0/0:27,0:27:60:0,60,900 1/1:0,65:65:99:2751,196,0 0/1:46,36:82:99:1184,0,1396 1/1:1,71:72:99:2746,179,0 0/0:34,0:34:90:0,90,1350 0/1:33,19:52:99:501,0,956 0/0:26,0:26:66:0,66,990 1/1:0,87:87:99:3474,261,0 0/1:48,36:84:99:1217,0,1377 0/1:66,69:135:99:2232,0,1854 0/0:47,0:47:96:0,96,1440 0/0:55,0:55:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:62,0:62:99:0,120,1800 0/0:52,0:52:99:0,105,1575 0/0:26,0:26:69:0,69,1035 0/0:27,0:27:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:34,0:34:69:0,69,1035 +20 13830179 rs62640920 G A 99044.30 PASS HWP=0.1394;AC=16;culprit=MQ;MQ0=0;ReadPosRankSum=0.486;AN=200;InbreedingCoeff=0.0664;AF=0.043;GQ_STDDEV=337.47;FS=1.103;DP=44606;GQ_MEAN=185.82;POSITIVE_TRAIN_SITE;VQSLOD=5.46;ClippingRankSum=0.192;BaseQRankSum=-2.798;MLEAF=0.043;MLEAC=75;MQ=59.51;QD=14.3;DB;MQRankSum=0.605;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:38,0:38:81:0,81,1215 0/0:39,0:39:96:0,96,1440 0/0:40,0:40:84:0,84,1260 0/1:40,50:90:99:1302,0,1272 0/1:44,49:93:99:1345,0,1265 0/1:55,37:92:99:1095,0,1639 0/0:37,0:37:75:0,75,1125 0/0:44,0:44:96:0,96,1440 0/0:62,0:62:99:0,120,1800 0/1:40,31:71:99:924,0,1162 0/1:50,36:86:99:1124,0,1504 0/1:40,30:70:99:902,0,1121 0/0:45,0:45:99:0,102,1530 0/1:42,41:83:99:1164,0,1239 0/0:35,0:35:87:0,87,1305 0/0:53,0:53:99:0,114,1710 0/0:42,0:42:87:0,87,1305 0/1:48,44:92:99:1190,0,1365 0/0:52,0:52:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:42,0:42:88:0,88,1358 0/0:64,0:64:99:0,120,1800 0/0:48,0:48:99:0,111,1665 0/0:54,0:54:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:36,0:36:93:0,93,979 0/0:42,0:42:66:0,66,990 0/0:36,0:36:90:0,90,1350 0/0:70,0:70:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/1:85,122:207:99:3389,0,2761 0/1:86,48:134:99:1283,0,2829 0/0:61,0:61:99:0,120,1800 0/0:41,0:41:90:0,90,1350 0/0:38,0:38:87:0,87,1305 0/0:33,0:33:81:0,81,1215 0/1:55,52:107:99:1595,0,1525 0/0:35,0:35:72:0,72,1080 0/0:32,0:32:70:0,70,1251 0/0:27,0:27:60:0,60,900 0/0:37,0:37:69:0,69,1035 0/0:44,0:44:99:0,99,1485 0/0:52,0:52:94:0,94,1543 0/0:42,0:42:81:0,81,1215 0/0:35,0:35:84:0,84,1260 0/0:48,0:48:99:0,99,1485 0/0:51,0:51:99:0,114,1710 0/1:41,32:73:99:942,0,1370 0/1:40,33:73:99:962,0,1271 0/0:21,0:21:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:46,0:46:99:0,99,1485 0/0:27,0:27:66:0,66,990 0/0:41,0:41:92:0,92,1530 0/0:48,0:48:99:0,117,1755 0/0:47,0:47:99:0,105,1575 0/0:52,0:52:99:0,114,1710 0/0:40,0:40:87:0,87,1305 0/0:30,0:30:75:0,75,1125 0/0:57,0:57:99:0,99,1485 0/0:34,0:34:78:0,78,1170 0/0:37,0:37:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:44,0:44:99:0,105,1575 0/0:28,0:28:69:0,69,1035 0/1:42,50:92:99:1337,0,1515 0/0:33,0:33:75:0,75,1125 0/1:67,66:133:99:1898,0,2154 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:43,0:43:93:0,93,1395 0/0:38,0:38:81:0,81,1215 0/0:42,0:42:87:0,87,1305 0/0:34,0:34:90:0,90,1350 0/0:25,0:25:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:39,0:39:72:0,72,1080 0/0:32,0:32:71:0,71,1125 0/0:55,0:55:99:0,120,1800 0/0:47,0:47:96:0,96,1440 0/0:55,0:55:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/1:75,78:153:99:2209,0,2269 0/0:73,0:73:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:62,0:62:99:0,120,1800 0/0:52,0:52:99:0,105,1575 0/0:26,0:26:69:0,69,1035 0/0:27,0:27:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:34,0:34:69:0,69,1035 +20 13839933 . T C 1572.31 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=1.49;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=38.68;FS=1.386;DP=21237;GQ_MEAN=62.86;VQSLOD=2.52;ClippingRankSum=-0.168;BaseQRankSum=4.0;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=11.65;MQRankSum=0.782;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,990 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:29,0:29:62:0,62,945 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,829 0/0:23,0:23:63:0,63,945 0/0:22,0:22:61:0,61,813 0/1:30,20:50:99:622,0,904 0/0:24,0:24:60:0,60,879 0/0:27,0:27:60:0,60,900 0/1:49,36:85:99:1027,0,1275 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:35,0:35:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:26,0:26:72:0,72,907 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,867 0/0:28,0:28:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,775 0/0:22,0:22:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:20,0:20:60:0,60,704 0/0:21,0:21:60:0,60,840 0/0:26,0:26:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:22,0:22:63:0,63,919 0/0:25,0:25:69:0,69,1016 0/0:27,0:27:78:0,78,1170 0/0:21,0:21:63:0,63,845 0/0:22,0:22:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:36,0:36:90:0,90,1350 0/0:31,0:31:78:0,78,1170 0/0:13,0:13:27:0,27,405 0/0:15,0:15:28:0,28,495 0/0:21,0:21:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:63:0,63,917 0/0:28,0:28:69:0,69,1035 0/0:33,0:33:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:31,0:31:75:0,75,1247 0/0:15,0:15:30:0,30,450 0/0:23,0:23:60:0,60,899 0/0:25,0:25:63:0,63,929 0/0:22,0:22:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:25,0:25:60:0,60,900 0/0:27,0:27:66:0,66,975 0/0:12,0:12:24:0,24,360 0/0:28,0:28:60:0,60,900 0/0:23,0:23:66:0,66,990 0/0:22,0:22:60:0,60,945 0/0:20,0:20:60:0,60,723 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:21,0:21:60:0,60,765 0/0:21,0:21:60:0,60,724 0/0:25,0:25:62:0,62,891 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,899 0/0:8,0:8:23:0,23,269 0/0:10,0:10:20:0,20,360 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,732 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,676 0/0:21,0:21:60:0,60,900 0/0:33,0:33:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:26,0:26:72:0,72,1080 0/0:23,0:23:60:0,60,900 0/0:29,0:29:78:0,78,1168 0/0:22,0:22:60:0,60,843 0/0:20,0:20:60:0,60,730 0/0:23,0:23:60:0,60,900 0/0:24,0:24:69:0,69,1035 0/0:20,0:20:60:0,60,723 +20 13845828 rs181883053 G A 4126.69 PASS HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=1.26;AN=200;InbreedingCoeff=-0.0017;AF=0.001724;GQ_STDDEV=72.03;FS=11.203;DP=59872;GQ_MEAN=117.68;POSITIVE_TRAIN_SITE;VQSLOD=1.95;ClippingRankSum=-0.605;BaseQRankSum=2.24;MLEAF=0.001724;MLEAC=3;MQ=58.4;QD=12.47;DB;MQRankSum=0.774;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:49,0:49:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:38,0:38:99:0,99,1485 0/0:65,0:65:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/1:54,47:101:99:1331,0,1403 0/0:91,0:91:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:98,0:98:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:121,0:121:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:51,0:51:99:0,112,1800 0/0:114,0:114:99:0,120,1800 0/0:130,0:130:99:0,120,1800 0/0:121,0:121:99:0,120,1800 0/1:65,53:118:99:1280,0,1667 0/0:49,0:49:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:138,0:138:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:52,0:52:99:0,107,1800 0/0:91,0:91:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:98,0:98:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:111,0:111:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:144,0:144:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:102,0:102:99:0,120,1800 0/0:47,0:47:99:0,114,1710 0/0:38,0:38:99:0,102,1528 0/0:154,0:154:99:0,120,1800 0/0:45,0:45:99:0,99,1710 0/0:79,0:79:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:51,0:51:99:0,112,1800 0/0:69,0:69:99:0,120,1800 0/0:44,0:44:99:0,114,1710 0/0:65,0:65:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:38,0:38:99:0,99,1485 0/0:45,0:45:99:0,105,1575 0/0:38,0:38:99:0,105,1575 0/0:73,0:73:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:43,0:43:99:0,105,1575 0/0:32,0:32:63:0,63,945 0/0:80,0:80:99:0,120,1800 0/0:120,0:120:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:37,0:37:87:0,87,1305 0/0:45,0:45:99:0,108,1620 0/0:56,0:56:99:0,120,1800 0/0:41,0:41:99:0,104,1575 0/0:76,0:76:99:0,120,1800 +20 13845987 rs761811 C T 3742800.00 PASS HWP=1.0;AC=198;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.933;AN=200;InbreedingCoeff=-0.0052;AF=0.995;GQ_STDDEV=207.23;FS=1.112;DP=113203;GQ_MEAN=403.13;POSITIVE_TRAIN_SITE;VQSLOD=3.4;ClippingRankSum=0.102;BaseQRankSum=0.874;MLEAF=0.995;MLEAC=1731;MQ=59.61;QD=33.14;DB;MQRankSum=0.506;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,90:90:99:3087,271,0 1/1:0,79:79:99:2662,237,0 1/1:0,87:87:99:2871,261,0 1/1:0,115:115:99:3743,345,0 1/1:0,90:90:99:3004,270,0 1/1:0,123:123:99:4156,370,0 1/1:0,95:95:99:3495,286,0 1/1:0,74:74:99:2620,223,0 1/1:0,102:102:99:3692,307,0 1/1:0,97:97:99:3054,291,0 1/1:0,100:100:99:3428,301,0 1/1:0,87:87:99:2852,261,0 1/1:0,110:110:99:3790,330,0 1/1:0,65:65:99:2164,195,0 1/1:1,139:140:99:4782,389,0 1/1:0,181:181:99:6253,544,0 1/1:0,137:137:99:4644,412,0 1/1:0,208:208:99:6977,624,0 1/1:0,169:169:99:5774,508,0 1/1:0,238:238:99:7901,715,0 1/1:0,176:176:99:5900,529,0 1/1:1,205:206:99:6909,590,0 1/1:0,201:201:99:6895,604,0 1/1:0,236:236:99:7679,708,0 1/1:0,265:265:99:8608,795,0 1/1:0,112:112:99:3832,336,0 1/1:0,140:140:99:4848,420,0 1/1:0,141:141:99:4910,424,0 1/1:1,156:157:99:5037,446,0 1/1:0,146:146:99:4959,439,0 1/1:0,137:137:99:4358,411,0 1/1:1,118:119:99:3900,323,0 1/1:0,207:207:99:7240,623,0 1/1:0,237:237:99:8219,713,0 1/1:0,199:199:99:6924,597,0 1/1:0,130:130:99:4059,390,0 1/1:0,109:109:99:3462,327,0 1/1:0,187:187:99:6273,562,0 1/1:0,122:122:99:4296,367,0 1/1:0,161:161:99:5626,483,0 1/1:0,95:95:99:3351,286,0 1/1:0,96:96:99:3450,289,0 1/1:0,103:103:99:3699,310,0 1/1:0,126:126:99:4504,379,0 1/1:0,129:129:99:4601,387,0 1/1:0,153:153:99:5358,459,0 1/1:0,139:139:99:4807,418,0 0/1:75,75:150:99:2198,0,2429 1/1:0,198:198:99:7187,595,0 1/1:0,211:211:99:7343,634,0 1/1:0,110:110:99:3956,331,0 1/1:0,104:104:99:3661,313,0 1/1:0,117:117:99:4042,352,0 1/1:0,107:107:99:3459,321,0 1/1:0,176:176:99:5978,529,0 1/1:1,140:141:99:4521,412,0 1/1:0,131:131:99:4880,394,0 1/1:0,151:151:99:5493,454,0 1/1:0,164:164:99:5670,493,0 1/1:0,187:187:99:6685,562,0 1/1:0,138:138:99:4828,414,0 1/1:0,124:124:99:4396,372,0 1/1:0,199:199:99:6832,598,0 1/1:0,108:108:99:3881,325,0 1/1:0,106:106:99:3685,319,0 1/1:0,205:205:99:7004,616,0 1/1:0,74:74:99:2573,222,0 1/1:0,58:58:99:2003,174,0 1/1:0,195:195:99:6814,586,0 1/1:0,97:97:99:3241,292,0 1/1:0,177:177:99:5976,532,0 1/1:0,102:102:99:3501,307,0 1/1:0,192:192:99:6580,577,0 1/1:0,105:105:99:3291,314,0 1/1:1,110:111:99:3609,324,0 1/1:0,112:112:99:3853,337,0 1/1:0,112:112:99:3791,337,0 1/1:0,96:96:99:3321,289,0 1/1:0,114:114:99:4022,343,0 1/1:0,137:137:99:4728,412,0 1/1:0,88:88:99:2962,264,0 1/1:0,94:94:99:3071,282,0 0/1:42,45:87:99:1152,0,1387 1/1:0,142:142:99:4873,427,0 1/1:0,113:113:99:3810,339,0 1/1:0,154:154:99:5381,463,0 1/1:0,116:116:99:3527,348,0 1/1:0,103:103:99:3483,309,0 1/1:0,187:187:99:6362,562,0 1/1:0,187:187:99:6455,562,0 1/1:1,171:172:99:5290,510,0 1/1:0,114:114:99:3680,342,0 1/1:0,98:98:99:3456,294,0 1/1:0,80:80:99:2651,240,0 1/1:0,111:111:99:3756,334,0 1/1:0,103:103:99:3285,309,0 1/1:0,69:69:99:2423,207,0 1/1:0,123:123:99:4243,370,0 1/1:0,81:81:99:2700,243,0 1/1:0,159:159:99:5407,478,0 +20 13846191 rs761812 A G 424724.00 PASS HWP=0.5839;AC=72;culprit=MQ;MQ0=0;ReadPosRankSum=0.264;AN=200;InbreedingCoeff=0.0203;AF=0.337;GQ_STDDEV=331.85;FS=0.0;DP=34556;GQ_MEAN=306.72;POSITIVE_TRAIN_SITE;VQSLOD=6.9;ClippingRankSum=-0.097;BaseQRankSum=1.58;MLEAF=0.337;MLEAC=587;MQ=60.0;QD=19.9;DB;MQRankSum=0.068;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:8,16:24:99:540,0,246 0/1:15,16:31:99:523,0,441 0/1:14,19:33:99:510,0,430 0/1:17,16:33:99:510,0,574 0/1:22,19:41:99:598,0,647 0/1:29,24:53:99:744,0,911 0/1:31,23:54:99:695,0,967 0/1:20,17:37:99:489,0,609 0/1:30,23:53:99:788,0,927 0/1:17,16:33:99:516,0,496 0/1:20,26:46:99:750,0,626 0/1:20,18:38:99:484,0,631 0/0:38,0:38:78:0,78,1170 0/1:21,22:43:99:596,0,635 0/0:35,0:35:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/1:17,29:46:99:877,0,487 0/0:38,0:38:92:0,92,1395 0/1:31,32:63:99:1025,0,888 0/0:25,0:25:60:0,60,900 0/0:26,0:26:63:0,63,945 0/1:23,24:47:99:746,0,725 0/0:63,0:63:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:43,0:43:99:0,111,1665 0/0:43,0:43:99:0,100,1620 0/1:12,28:40:99:919,0,343 0/1:18,17:35:99:550,0,557 0/1:18,17:35:99:537,0,535 0/1:20,12:32:99:380,0,656 0/0:74,0:74:99:0,120,1800 0/1:49,40:89:99:1339,0,1550 0/1:38,45:83:99:1469,0,1139 0/0:28,0:28:63:0,63,945 0/0:27,0:27:63:0,63,945 1/1:0,43:43:99:1566,129,0 1/1:0,49:49:99:1895,147,0 0/1:29,36:65:99:1175,0,850 0/0:38,0:38:96:0,96,1440 1/1:0,28:28:84:1104,84,0 0/1:23,26:49:99:856,0,711 0/0:44,0:44:99:0,99,1485 0/0:43,0:43:99:0,117,1755 0/0:55,0:55:99:0,120,1800 0/1:22,26:48:99:904,0,620 0/0:52,0:52:99:0,120,1800 0/0:50,0:50:99:0,111,1665 0/0:61,0:61:99:0,120,1800 1/1:0,49:49:99:1939,147,0 0/1:22,19:41:99:628,0,703 0/1:15,20:35:99:629,0,466 0/0:36,0:36:84:0,84,1260 0/0:49,0:49:99:0,108,1620 0/0:37,0:37:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/1:27,35:62:99:1174,0,821 0/1:24,23:47:99:717,0,723 0/0:56,0:56:99:0,120,1800 1/1:0,49:49:99:1880,147,0 0/1:24,30:54:99:973,0,710 0/0:79,0:79:99:0,120,1800 0/0:37,0:37:84:0,84,1305 1/1:0,41:41:99:1547,123,0 1/1:0,37:37:99:1399,111,0 0/0:27,0:27:66:0,66,990 0/0:29,0:29:57:0,57,855 0/1:27,33:60:99:1202,0,884 0/0:24,0:24:60:0,60,900 0/1:34,27:61:99:909,0,1101 0/1:29,17:46:99:507,0,945 0/1:50,37:87:99:1295,0,1462 0/0:33,0:33:81:0,81,1215 0/0:35,0:35:66:0,66,990 0/0:39,0:39:90:0,90,1350 0/1:28,19:47:99:582,0,883 0/0:26,0:26:60:0,60,900 0/1:26,22:48:99:779,0,832 0/0:44,0:44:99:0,101,1480 0/1:13,17:30:99:554,0,395 0/1:20,16:36:99:528,0,639 0/1:12,15:27:99:520,0,394 0/0:39,0:39:84:0,84,1260 0/1:22,19:41:99:650,0,743 0/1:30,30:60:99:971,0,960 1/1:0,30:30:90:1179,90,0 0/1:11,16:27:99:511,0,363 0/1:23,30:53:99:922,0,697 0/1:48,44:92:99:1480,0,1552 1/1:0,36:36:99:1390,108,0 0/0:25,0:25:66:0,66,990 0/1:22,30:52:99:975,0,679 1/1:0,33:33:99:1352,99,0 1/1:1,43:44:96:1690,96,0 0/0:31,0:31:60:0,60,900 0/1:23,16:39:99:547,0,748 0/1:18,17:35:99:602,0,534 0/1:15,24:39:99:794,0,471 1/1:1,35:36:68:1311,68,0 +20 13847420 rs660710 A G 3564520.00 PASS HWP=1.0;AC=198;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.563;AN=200;InbreedingCoeff=-0.0064;AF=0.994;GQ_STDDEV=184.09;FS=1.183;DP=98800;GQ_MEAN=352.87;POSITIVE_TRAIN_SITE;VQSLOD=3.67;ClippingRankSum=0.127;BaseQRankSum=1.67;MLEAF=0.994;MLEAC=1729;MQ=59.72;QD=29.82;DB;MQRankSum=0.055;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,118:118:99:4383,355,0 1/1:0,93:93:99:3498,280,0 1/1:0,95:95:99:3473,286,0 1/1:0,100:100:99:3752,300,0 1/1:0,129:129:99:4660,388,0 1/1:0,101:101:99:3658,304,0 1/1:0,131:131:99:4960,394,0 1/1:0,91:91:99:3277,273,0 1/1:0,96:96:99:3678,289,0 1/1:0,99:99:99:3618,298,0 1/1:1,124:125:99:4588,364,0 1/1:0,107:107:99:3824,321,0 1/1:0,115:115:99:4407,346,0 1/1:0,95:95:99:3441,286,0 1/1:0,75:75:99:2555,226,0 1/1:0,110:110:99:3877,330,0 1/1:0,99:99:99:3433,298,0 1/1:0,112:112:99:3913,337,0 1/1:0,113:113:99:3932,339,0 1/1:0,138:138:99:4927,415,0 1/1:0,96:96:99:3450,289,0 1/1:0,118:118:99:4195,355,0 1/1:0,111:111:99:3991,334,0 1/1:1,202:203:99:7286,607,0 1/1:0,197:197:99:7029,592,0 1/1:0,101:101:99:3618,302,0 1/1:0,121:121:99:4237,363,0 1/1:0,112:112:99:4001,337,0 1/1:0,103:103:99:3769,309,0 1/1:0,106:106:99:3983,318,0 1/1:0,103:103:99:3783,309,0 1/1:0,134:134:99:4881,403,0 1/1:0,171:171:99:6236,512,0 1/1:0,241:241:99:9191,724,0 1/1:0,175:175:99:6265,523,0 1/1:0,138:138:99:4634,415,0 1/1:0,123:123:99:4513,370,0 1/1:0,129:129:99:4505,387,0 1/1:0,87:87:99:3055,260,0 1/1:0,131:131:99:4574,393,0 1/1:0,84:84:99:3036,253,0 1/1:0,113:113:99:3814,337,0 1/1:0,108:108:99:3833,324,0 1/1:0,89:89:99:3229,267,0 1/1:0,101:101:99:3633,302,0 1/1:0,110:110:99:3886,329,0 1/1:0,121:121:99:4340,363,0 0/1:70,62:132:99:1840,0,2084 1/1:0,140:140:99:5359,421,0 1/1:0,177:177:99:6800,532,0 1/1:0,92:92:99:3282,275,0 1/1:0,94:94:99:3486,282,0 1/1:0,98:98:99:3323,294,0 1/1:0,118:118:99:4471,355,0 1/1:0,165:165:99:6349,496,0 1/1:0,106:106:99:3769,318,0 1/1:0,120:120:99:4381,360,0 1/1:0,98:98:99:3581,293,0 1/1:0,133:133:99:4656,399,0 1/1:0,159:159:99:6312,478,0 1/1:0,98:98:99:3324,295,0 1/1:0,101:101:99:3513,302,0 1/1:0,194:194:99:7563,583,0 1/1:0,118:118:99:4037,353,0 1/1:2,117:119:99:4197,308,0 1/1:0,95:95:99:3417,286,0 1/1:0,96:96:99:3540,288,0 1/1:0,52:52:99:2022,156,0 1/1:0,180:180:99:6947,541,0 1/1:0,81:81:99:3127,243,0 1/1:0,179:179:99:6870,538,0 1/1:0,80:80:99:3140,241,0 1/1:0,187:187:99:6882,562,0 1/1:0,121:121:99:4575,364,0 1/1:0,94:94:99:3584,281,0 1/1:0,83:83:99:3283,250,0 1/1:0,104:104:99:3992,313,0 1/1:0,105:105:99:4074,316,0 1/1:0,86:86:99:3380,259,0 1/1:0,130:130:99:4878,390,0 1/1:0,73:73:99:2731,219,0 1/1:0,80:80:99:2941,239,0 0/1:28,40:68:99:1284,0,793 1/1:0,115:115:99:4537,346,0 1/1:0,116:116:99:4451,349,0 1/1:0,186:186:99:7028,559,0 1/1:0,142:142:99:4961,427,0 1/1:0,127:127:99:4425,382,0 1/1:0,112:112:99:3875,336,0 1/1:0,176:176:99:6780,529,0 1/1:0,145:145:99:5309,436,0 1/1:0,155:155:99:5676,466,0 1/1:0,119:119:99:4589,358,0 1/1:0,89:89:99:3472,268,0 1/1:0,112:112:99:4103,337,0 1/1:0,116:116:99:3869,347,0 1/1:0,88:88:99:3322,265,0 1/1:0,91:91:99:3477,273,0 1/1:0,75:75:99:2981,226,0 1/1:0,101:101:99:3757,303,0 +20 13867034 rs139504161 G A 1199.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=-0.25;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=42.87;FS=1.833;DP=23103;GQ_MEAN=68.31;VQSLOD=2.42;ClippingRankSum=-0.081;BaseQRankSum=-1.507;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=13.79;DB;MQRankSum=-1.651;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:27,0:27:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,790 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,708 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:63:0,63,880 0/0:29,0:29:64:0,64,1170 0/0:28,0:28:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:27,0:27:68:0,68,1125 0/0:30,0:30:69:0,69,1035 0/0:30,0:30:87:0,87,1267 0/0:31,0:31:84:0,84,1147 0/0:24,0:24:60:0,60,900 0/0:32,0:32:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:26,0:26:78:0,78,1017 0/0:22,0:22:66:0,66,857 0/0:26,0:26:69:0,69,1035 0/0:34,0:34:87:0,87,1305 0/0:31,0:31:75:0,75,1125 0/0:26,0:26:67:0,67,1027 0/0:27,0:27:63:0,63,945 0/0:26,0:26:65:0,65,960 0/0:26,0:26:66:0,66,990 0/0:20,0:20:60:0,60,739 0/0:37,0:37:99:0,108,1620 0/0:38,0:38:99:0,111,1665 0/0:39,0:39:99:0,105,1575 0/0:20,0:20:60:0,60,660 0/0:28,0:28:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:21,0:21:63:0,63,840 0/0:27,0:27:81:0,81,1083 0/0:29,0:29:61:0,61,990 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:26,0:26:75:0,75,1035 0/0:32,0:32:72:0,72,1080 0/0:28,0:28:72:0,72,1080 0/0:29,0:29:64:0,64,1114 0/0:37,0:37:81:0,81,1215 0/1:44,43:87:99:1250,0,1332 0/0:26,0:26:72:0,72,1047 0/0:20,0:20:60:0,60,802 0/0:24,0:24:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:28,0:28:81:0,81,1215 0/0:21,0:21:60:0,60,846 0/0:37,0:37:96:0,96,1440 0/0:40,0:40:99:0,99,1485 0/0:28,0:28:81:0,81,1132 0/0:33,0:33:87:0,87,1305 0/0:31,0:31:74:0,74,1170 0/0:33,0:33:78:0,78,1170 0/0:41,0:41:99:0,102,1546 0/0:37,0:37:93:0,93,1395 0/0:25,0:25:66:0,66,990 0/0:32,0:32:66:0,66,990 0/0:21,0:21:60:0,60,717 0/0:20,0:20:60:0,60,682 0/0:33,0:33:71:0,71,1080 0/0:22,0:22:60:0,60,900 0/0:40,0:40:99:0,102,1530 0/0:21,0:21:60:0,60,900 0/0:33,0:33:77:0,77,1260 0/0:22,0:22:60:0,60,898 0/0:28,0:28:69:0,69,1035 0/0:22,0:22:60:0,60,857 0/0:27,0:27:69:0,69,1035 0/0:32,0:32:60:0,60,900 0/0:25,0:25:69:0,69,1035 0/0:26,0:26:66:0,66,990 0/0:22,0:22:60:0,60,855 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:22,0:22:66:0,66,877 0/0:33,0:33:78:0,78,1170 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,820 0/0:24,0:24:69:0,69,957 0/0:47,0:47:99:0,114,1710 0/0:22,0:22:60:0,60,737 0/0:22,0:22:63:0,63,793 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,800 0/0:25,0:25:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:26,0:26:71:0,71,1032 +20 13868394 rs145289060 T A 20913.20 PASS HWP=1.0;AC=6;culprit=FS;MQ0=0;ReadPosRankSum=0.636;AN=200;InbreedingCoeff=-0.0099;AF=0.00977;GQ_STDDEV=165.94;FS=0.0;DP=25222;GQ_MEAN=85.21;POSITIVE_TRAIN_SITE;VQSLOD=6.09;ClippingRankSum=0.343;BaseQRankSum=3.72;MLEAF=0.00977;MLEAC=17;MQ=59.75;QD=16.05;DB;MQRankSum=0.12;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:60:0,60,900 0/0:30,0:30:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/1:45,34:79:99:986,0,1419 0/0:34,0:34:60:0,60,900 0/0:32,0:32:65:0,65,1125 0/0:27,0:27:60:0,60,900 0/0:34,0:34:78:0,78,1170 0/0:33,0:33:66:0,66,1094 0/1:29,38:67:99:1184,0,915 0/0:25,0:25:60:0,60,900 0/0:31,0:31:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:38,0:38:81:0,81,1215 0/0:27,0:27:63:0,63,945 0/0:38,0:38:84:0,84,1260 0/0:33,0:33:81:0,81,1135 0/0:43,0:43:98:0,98,1369 0/0:50,0:50:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/1:64,51:115:99:1469,0,1963 0/0:26,0:26:66:0,66,990 0/0:22,0:22:66:0,66,861 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:72:0,72,1078 0/0:25,0:25:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:34,0:34:87:0,87,1305 0/0:31,0:31:66:0,66,990 0/0:26,0:26:63:0,63,945 0/1:47,50:97:99:1610,0,1366 0/0:35,0:35:93:0,93,1395 0/1:53,73:126:99:2277,0,1576 0/0:20,0:20:60:0,60,747 0/0:27,0:27:63:0,63,945 0/0:33,0:33:71:0,71,1125 0/0:30,0:30:69:0,69,1035 0/0:32,0:32:84:0,84,1260 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/1:30,38:68:99:1302,0,880 0/0:32,0:32:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:40,0:40:96:0,96,1440 0/0:44,0:44:99:0,102,1530 0/0:27,0:27:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:30,0:30:78:0,78,1170 0/0:29,0:29:63:0,63,945 0/0:34,0:34:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:28,0:28:69:0,69,1035 0/0:52,0:52:99:0,117,1800 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,846 0/0:37,0:37:96:0,96,1440 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:38,0:38:78:0,78,1170 0/0:33,0:33:72:0,72,1080 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,817 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,745 0/0:21,0:21:60:0,60,726 0/0:30,0:30:66:0,66,990 0/0:32,0:32:71:0,71,1305 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:25,0:25:75:0,75,944 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:23,0:23:66:0,66,892 0/0:28,0:28:63:0,63,945 0/0:22,0:22:66:0,66,802 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,894 0/0:27,0:27:69:0,69,1035 +20 13869131 rs141957868 T C 9046.59 PASS HWP=1.0;AC=6;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.697;AN=200;InbreedingCoeff=-0.012;AF=0.00977;GQ_STDDEV=110.63;FS=3.34;DP=17414;GQ_MEAN=59.79;POSITIVE_TRAIN_SITE;VQSLOD=3.36;ClippingRankSum=0.455;BaseQRankSum=1.0;MLEAF=0.00977;MLEAC=17;MQ=59.23;QD=13.5;DB;MQRankSum=0.365;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:60:0,60,880 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,725 0/1:15,16:31:99:401,0,420 0/0:23,0:23:63:0,63,913 0/0:22,0:22:66:0,66,876 0/0:9,0:9:27:0,27,350 0/0:25,0:25:63:0,63,945 0/0:26,0:26:60:0,60,900 0/1:18,14:32:99:474,0,513 0/0:22,0:22:63:0,63,926 0/0:24,0:24:60:0,60,859 0/0:22,0:22:60:0,60,808 0/0:30,0:30:68:0,68,1025 0/0:36,0:36:72:0,72,1080 0/0:21,0:21:60:0,60,900 0/0:47,0:47:93:0,93,1395 0/0:36,0:36:72:0,72,1080 0/0:45,0:45:99:0,105,1575 0/0:29,0:29:60:0,60,900 0/1:45,45:90:99:1404,0,1195 0/0:27,0:27:78:0,78,1170 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,807 0/0:21,0:21:57:0,57,855 0/0:11,0:11:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,896 0/0:21,0:21:60:0,60,788 0/1:13,8:21:99:244,0,389 0/0:8,0:8:21:0,21,307 0/1:16,16:32:99:469,0,439 0/0:22,0:22:60:0,60,835 0/0:22,0:22:60:0,60,861 0/0:49,0:49:99:0,105,1575 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:8,0:8:21:0,21,276 0/0:8,0:8:21:0,21,298 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,274 0/0:12,0:12:30:0,30,450 0/1:7,5:12:99:136,0,206 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,783 0/0:30,0:30:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:8,0:8:21:0,21,304 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,266 0/0:7,0:7:21:0,21,267 0/0:9,0:9:21:0,21,315 0/0:20,0:20:60:0,60,631 0/0:11,0:11:24:0,24,360 0/0:7,0:7:21:0,21,244 0/0:8,0:8:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:7,0:7:21:0,21,240 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,350 0/0:11,0:11:30:0,30,371 0/0:8,0:8:21:0,21,263 0/0:35,0:35:75:0,75,1125 0/0:5,0:5:9:0,9,135 0/0:3,0:3:6:0,6,90 0/0:22,0:22:60:0,60,900 0/0:2,0:2:6:0,6,72 0/0:7,0:7:21:0,21,276 0/0:7,0:7:21:0,21,227 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,235 0/0:6,0:6:12:0,12,180 0/0:4,0:4:9:0,9,119 0/0:12,0:12:30:0,30,450 0/0:7,0:7:21:0,21,266 0/0:7,0:7:18:0,18,270 0/0:7,0:7:21:0,21,248 0/0:3,0:3:6:0,6,90 0/0:7,0:7:21:0,21,213 0/0:5,0:5:15:0,15,184 0/0:7,0:7:21:0,21,262 0/0:9,0:9:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:23,0:23:60:0,60,891 0/0:21,0:21:60:0,60,734 0/0:47,0:47:99:0,120,1800 0/0:21,0:21:60:0,60,654 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,642 0/0:5,0:5:6:0,6,90 0/0:8,0:8:21:0,21,273 0/0:20,0:20:60:0,60,681 0/0:21,0:21:60:0,60,900 0/0:4,0:4:9:0,9,135 0/0:8,0:8:21:0,21,267 0/0:2,0:2:6:0,6,49 0/0:9,0:9:21:0,21,315 +20 13869206 rs6135002 T C 71027.30 PASS HWP=9.0E-4;AC=26;culprit=MQ;MQ0=0;ReadPosRankSum=0.248;AN=182;InbreedingCoeff=0.0341;AF=0.176;GQ_STDDEV=87.56;FS=1.407;DP=8730;GQ_MEAN=54.86;POSITIVE_TRAIN_SITE;VQSLOD=4.4;ClippingRankSum=0.0;BaseQRankSum=2.2;MLEAF=0.192;MLEAC=322;MQ=60.0;QD=20.85;DB;MQRankSum=0.322;CCC=1680;NCC=30 GT:AD:DP:GQ:PL 0/0:10,0:10:21:0,21,315 0/0:14,0:14:24:0,24,360 0/1:6,4:10:99:135,0,181 0/1:9,6:15:99:188,0,275 0/1:6,5:11:99:159,0,184 0/1:2,6:8:44:215,0,44 0/0:14,0:14:33:0,33,495 0/0:15,0:15:33:0,33,495 0/1:9,6:15:99:208,0,271 0/1:9,7:16:99:237,0,279 0/1:10,14:24:99:482,0,304 0/1:5,7:12:99:245,0,142 0/0:10,0:10:27:0,27,405 1/1:1,14:15:8:530,8,0 0/1:16,17:33:99:512,0,461 0/0:36,0:36:72:0,72,1080 0/0:21,0:21:60:0,60,900 1/1:0,47:47:99:1766,141,0 0/0:36,0:36:72:0,72,1080 0/0:45,0:45:99:0,105,1575 0/0:29,0:29:60:0,60,900 0/0:39,0:39:90:0,90,1350 0/0:27,0:27:78:0,78,1170 0/0:6,0:6:9:0,9,135 0/0:6,0:6:0:0,0,154 0/0:5,0:5:9:0,9,135 0/0:4,0:4:9:0,9,135 0/0:7,0:7:12:0,12,180 0/0:14,0:14:36:0,36,540 0/0:5,0:5:6:0,6,90 0/1:5,8:13:99:294,0,126 0/0:11,0:11:21:0,21,315 0/0:5,0:5:15:0,15,183 0/0:5,0:5:0:0,0,15 0/1:5,6:11:99:223,0,127 0/0:5,0:5:6:0,6,90 0/1:3,5:8:84:195,0,84 0/0:49,0:49:99:0,105,1575 0/0:8,0:8:21:0,21,315 0/0:7,0:7:0:0,0,108 ./.:4,0:4:.:. 0/0:5,0:5:12:0,12,180 ./.:1,0:1:.:. 0/0:8,0:8:21:0,21,274 0/0:8,0:8:21:0,21,289 0/0:6,0:6:15:0,15,225 0/0:5,0:5:15:0,15,184 0/0:10,0:10:24:0,24,353 0/0:23,0:23:60:0,60,900 0/0:15,0:15:24:0,24,360 0/0:3,0:3:0:0,0,33 0/1:2,4:6:51:112,0,51 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,267 0/0:3,0:3:6:0,6,90 0/0:7,0:7:15:0,15,225 0/0:8,0:8:18:0,18,270 0/0:3,0:3:6:0,6,90 0/0:5,0:5:15:0,15,182 0/0:13,0:13:30:0,30,450 0/0:3,0:3:6:0,6,90 0/0:4,0:4:9:0,9,135 0/0:5,0:5:12:0,12,179 0/0:5,0:5:9:0,9,135 0/0:1,0:1:3:0,3,37 0/0:35,0:35:75:0,75,1125 0/0:5,0:5:6:0,6,90 0/0:2,0:2:3:0,3,45 0/0:10,0:10:21:0,21,315 ./.:1,0:1:.:. 0/0:2,0:2:0:0,0,6 ./.:1,0:1:.:. 0/1:5,4:9:99:146,0,153 0/0:7,0:7:9:0,9,135 0/0:5,0:5:12:0,12,180 0/0:2,0:2:3:0,3,45 0/0:2,0:2:6:0,6,73 0/0:3,0:3:6:0,6,86 0/0:7,0:7:15:0,15,225 0/0:1,0:1:3:0,3,33 0/0:2,0:2:6:0,6,75 0/0:2,0:2:6:0,6,71 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. 0/1:4,3:7:99:111,0,117 0/1:7,4:11:99:143,0,213 0/1:4,4:8:99:147,0,111 0/1:7,4:11:99:142,0,202 0/1:26,34:60:99:1044,0,754 0/0:2,0:2:0:0,0,36 0/0:12,0:12:0:0,0,230 1/1:0,15:15:45:568,45,0 ./.:0,0:0:.:. ./.:3,0:3:.:. 0/1:6,7:13:99:227,0,181 0/0:11,0:11:27:0,27,405 ./.:1,0:1:.:. 0/0:8,0:8:21:0,21,267 ./.:1,0:1:.:. 0/0:2,0:2:6:0,6,75 +20 13912308 rs143129534 C T 4878.27 PASS HWP=1.0;AC=3;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.09;AN=200;InbreedingCoeff=-0.0087;AF=0.007471;GQ_STDDEV=46.84;FS=16.512;DP=17172;GQ_MEAN=57.31;POSITIVE_TRAIN_SITE;VQSLOD=1.83;ClippingRankSum=-0.313;BaseQRankSum=-2.812;MLEAF=0.007471;MLEAC=13;MQ=60.0;QD=12.7;DB;MQRankSum=0.342;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:20,0:20:51:0,51,765 0/0:22,0:22:60:0,60,851 0/0:11,0:11:30:0,30,450 0/0:20,0:20:60:0,60,721 0/0:20,0:20:60:0,60,720 0/0:7,0:7:21:0,21,261 0/0:24,0:24:69:0,69,977 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,803 0/0:17,0:17:42:0,42,590 0/0:23,0:23:60:0,60,900 0/0:11,0:11:27:0,27,405 0/0:23,0:23:63:0,63,945 0/0:7,0:7:21:0,21,223 0/0:49,0:49:99:0,106,1800 0/0:27,0:27:69:0,69,1035 0/0:21,0:21:60:0,60,775 0/0:26,0:26:61:0,61,962 0/0:30,0:30:87:0,87,1305 0/0:32,0:32:81:0,81,1215 0/0:24,0:24:66:0,66,957 0/0:23,0:23:62:0,62,990 0/0:25,0:25:75:0,75,924 0/0:21,0:21:63:0,63,726 0/0:21,0:21:60:0,60,870 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,781 0/0:20,0:20:60:0,60,682 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,668 0/0:39,0:39:89:0,89,1238 0/0:7,0:7:21:0,21,246 0/0:21,0:21:60:0,60,900 0/0:21,0:21:63:0,63,739 0/0:22,0:22:60:0,60,900 0/0:8,0:8:21:0,21,290 0/0:7,0:7:21:0,21,291 0/0:31,0:31:87:0,87,1305 0/0:21,0:21:60:0,60,787 0/0:28,0:28:78:0,78,1170 0/0:21,0:21:57:0,57,855 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,804 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,849 0/0:23,0:23:63:0,63,990 0/0:20,0:20:60:0,60,759 0/0:24,0:24:63:0,63,990 0/0:24,0:24:69:0,69,1035 0/0:22,0:22:60:0,60,847 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/1:25,16:41:99:455,0,809 0/0:29,0:29:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,786 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,771 0/0:26,0:26:63:0,63,990 0/0:24,0:24:63:0,63,945 0/0:29,0:29:78:0,78,1170 0/0:7,0:7:21:0,21,270 0/0:8,0:8:21:0,21,315 0/0:33,0:33:93:0,93,1395 0/0:7,0:7:21:0,21,250 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:20,0:20:60:0,60,795 0/0:22,0:22:63:0,63,775 0/0:13,0:13:36:0,36,540 0/0:7,0:7:21:0,21,254 0/0:7,0:7:21:0,21,256 0/1:11,12:23:99:376,0,794 0/1:10,8:18:99:234,0,335 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:8,0:8:24:0,24,296 0/0:24,0:24:66:0,66,990 0/0:20,0:20:60:0,60,732 0/0:21,0:21:60:0,60,821 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,268 0/0:29,0:29:78:0,78,1170 0/0:21,0:21:60:0,60,763 0/0:7,0:7:21:0,21,249 0/0:7,0:7:21:0,21,216 0/0:21,0:21:60:0,60,900 0/0:15,0:15:42:0,42,556 0/0:7,0:7:21:0,21,238 0/0:11,0:11:30:0,30,413 0/0:7,0:7:21:0,21,267 0/0:22,0:22:60:0,60,900 0/0:11,0:11:30:0,30,450 0/0:21,0:21:60:0,60,900 +20 13912309 rs41275404 G A 37348.70 PASS HWP=0.6213;AC=15;culprit=MQ;MQ0=0;ReadPosRankSum=0.412;AN=200;InbreedingCoeff=0.0233;AF=0.048;GQ_STDDEV=142.8;FS=5.019;DP=18482;GQ_MEAN=86.98;POSITIVE_TRAIN_SITE;VQSLOD=3.16;ClippingRankSum=-0.106;BaseQRankSum=1.96;MLEAF=0.048;MLEAC=83;MQ=60.0;QD=13.7;DB;MQRankSum=0.318;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:20,0:20:51:0,51,765 0/0:22,0:22:60:0,60,851 0/0:11,0:11:30:0,30,450 0/0:20,0:20:60:0,60,721 0/0:20,0:20:60:0,60,720 0/0:7,0:7:21:0,21,261 0/0:31,0:31:54:0,54,1080 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,803 0/0:17,0:17:42:0,42,590 0/0:23,0:23:60:0,60,900 0/0:11,0:11:27:0,27,405 0/0:23,0:23:63:0,63,945 0/1:11,7:18:99:208,0,353 0/0:49,0:49:99:0,106,1800 0/0:27,0:27:69:0,69,1035 0/0:21,0:21:60:0,60,775 0/1:46,24:70:99:703,0,1449 0/0:30,0:30:87:0,87,1305 0/0:32,0:32:81:0,81,1215 0/0:24,0:24:66:0,66,957 0/1:41,39:80:99:1199,0,1213 0/0:25,0:25:75:0,75,924 0/0:21,0:21:63:0,63,726 0/0:21,0:21:60:0,60,870 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,781 0/0:20,0:20:60:0,60,682 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,668 0/0:39,0:39:89:0,89,1238 0/0:7,0:7:21:0,21,246 0/1:28,28:56:99:834,0,847 0/0:21,0:21:63:0,63,739 0/0:22,0:22:60:0,60,900 0/0:8,0:8:21:0,21,290 0/0:7,0:7:21:0,21,291 0/0:31,0:31:87:0,87,1305 0/0:21,0:21:60:0,60,787 0/0:28,0:28:78:0,78,1170 0/0:22,0:22:60:0,60,900 1/1:0,22:22:66:832,66,0 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,804 0/1:21,18:39:99:579,0,608 0/0:23,0:23:60:0,60,849 0/0:23,0:23:63:0,63,990 0/0:20,0:20:60:0,60,759 0/0:24,0:24:63:0,63,990 0/0:24,0:24:69:0,69,1035 0/0:22,0:22:60:0,60,847 0/1:10,17:27:99:560,0,255 0/0:22,0:22:60:0,60,900 0/1:19,12:31:99:364,0,598 0/0:43,0:43:66:0,66,1635 0/0:29,0:29:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,786 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,771 0/0:26,0:26:63:0,63,990 0/1:22,6:28:99:142,0,668 0/0:29,0:29:78:0,78,1170 0/0:7,0:7:21:0,21,270 0/0:8,0:8:21:0,21,315 0/1:30,24:54:99:756,0,923 0/0:7,0:7:21:0,21,250 0/0:24,0:24:63:0,63,945 0/1:8,17:25:99:573,0,228 0/0:25,0:25:66:0,66,990 0/0:20,0:20:60:0,60,795 0/0:22,0:22:63:0,63,775 0/0:13,0:13:2:0,2,419 0/0:20,0:20:60:0,60,755 0/0:7,0:7:21:0,21,256 0/1:12,11:23:99:346,0,912 0/0:20,0:20:57:0,57,855 0/1:8,11:19:99:337,0,241 0/1:4,5:9:99:157,0,128 0/0:8,0:8:24:0,24,296 0/0:24,0:24:66:0,66,990 0/0:20,0:20:60:0,60,732 0/0:21,0:21:60:0,60,821 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,268 0/0:29,0:29:78:0,78,1170 0/0:21,0:21:60:0,60,763 0/0:7,0:7:21:0,21,249 0/0:7,0:7:21:0,21,216 0/0:21,0:21:60:0,60,900 0/0:15,0:15:42:0,42,556 0/0:7,0:7:21:0,21,238 0/0:11,0:11:30:0,30,413 0/0:7,0:7:21:0,21,267 0/0:22,0:22:60:0,60,900 0/0:11,0:11:30:0,30,450 0/0:21,0:21:60:0,60,900 +20 13976466 . C T 4712.10 PASS HWP=1.0;AC=3;culprit=MQ;MQ0=0;ReadPosRankSum=-0.365;AN=186;InbreedingCoeff=-0.044;AF=0.014;GQ_STDDEV=28.78;FS=3.457;DP=8747;GQ_MEAN=24.03;VQSLOD=1.37;ClippingRankSum=0.365;BaseQRankSum=1.87;MLEAF=0.015;MLEAC=25;MQ=60.0;QD=13.7;MQRankSum=0.365;CCC=1710;NCC=15 GT:AD:DP:GQ:PL 0/0:11,0:11:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:7,0:7:21:0,21,254 0/0:4,0:4:6:0,6,90 0/0:8,0:8:21:0,21,282 0/0:4,0:4:6:0,6,90 0/0:13,0:13:21:0,21,315 0/0:8,0:8:21:0,21,297 0/0:9,0:9:21:0,21,315 0/0:14,0:14:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,251 0/0:10,0:10:21:0,21,315 0/0:4,0:4:6:0,6,90 0/0:9,0:9:21:0,21,315 0/0:8,0:8:20:0,20,295 0/1:6,7:13:99:190,0,167 0/0:7,0:7:12:0,12,180 0/0:2,0:2:6:0,6,60 0/0:9,0:9:21:0,21,315 0/1:4,5:9:99:138,0,99 0/0:3,0:3:9:0,9,103 0/0:12,0:12:21:0,21,315 0/0:11,0:11:27:0,27,405 0/0:13,0:13:21:0,21,315 0/0:8,0:8:0:0,0,105 0/0:12,0:12:27:0,27,405 0/0:11,0:11:24:0,24,360 0/0:14,0:14:27:0,27,405 0/0:14,0:14:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:15,0:15:20:0,20,405 0/0:13,0:13:21:0,21,315 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:3,6:9:80:203,0,80 0/0:12,0:12:24:0,24,360 0/0:7,0:7:21:0,21,239 0/0:5,0:5:6:0,6,90 0/0:9,0:9:21:0,21,315 ./.:0,0:0:.:. 0/0:3,0:3:6:0,6,90 0/0:4,0:4:9:0,9,135 0/0:3,0:3:6:0,6,90 0/0:13,0:13:21:0,21,315 ./.:0,0:0:.:. 0/0:11,0:11:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:5,0:5:12:0,12,180 0/0:7,0:7:21:0,21,256 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,68 0/0:2,0:2:6:0,6,75 ./.:0,0:0:.:. 0/0:7,0:7:6:0,6,90 0/0:8,0:8:21:0,21,315 0/0:5,0:5:6:0,6,90 0/0:8,0:8:21:0,21,315 0/0:13,0:13:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,253 0/0:23,0:23:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:11,0:11:21:0,21,315 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,83 0/0:4,0:4:6:0,6,90 ./.:0,0:0:.:. 0/0:9,0:9:20:0,20,315 0/0:5,0:5:6:0,6,90 0/0:9,0:9:21:0,21,315 0/0:4,0:4:6:0,6,90 0/0:4,0:4:9:0,9,135 0/0:3,0:3:6:0,6,90 0/0:9,0:9:21:0,21,315 0/0:2,0:2:6:0,6,49 0/0:4,0:4:6:0,6,90 0/0:4,0:4:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,315 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,79 0/0:12,0:12:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:4,0:4:6:0,6,90 0/0:11,0:11:21:0,21,315 0/0:28,0:28:63:0,63,945 0/0:11,0:11:24:0,24,360 0/0:4,0:4:6:0,6,90 0/0:2,0:2:6:0,6,65 0/0:12,0:12:27:0,27,405 0/0:11,0:11:21:0,21,315 0/0:4,0:4:6:0,6,90 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. 0/0:3,0:3:6:0,6,90 +20 13983008 rs145602631 C T 2255.69 PASS HWP=1.0;AC=1;culprit=MQRankSum;MQ0=0;ReadPosRankSum=0.499;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=73.08;FS=2.987;DP=24620;GQ_MEAN=77.81;VQSLOD=2.02;ClippingRankSum=-0.843;BaseQRankSum=-3.624;MLEAF=5.747E-4;MLEAC=1;MQ=59.11;QD=14.74;DB;MQRankSum=-0.47;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:21,0:21:60:0,60,861 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:24,0:24:69:0,69,1035 0/0:26,0:26:69:0,69,1035 0/0:25,0:25:72:0,72,1031 0/0:20,0:20:60:0,60,715 0/0:26,0:26:78:0,78,1059 0/0:20,0:20:60:0,60,733 0/0:21,0:21:60:0,60,798 0/0:21,0:21:60:0,60,743 0/0:21,0:21:63:0,63,781 0/0:24,0:24:66:0,66,990 0/0:41,0:41:99:0,105,1575 0/0:28,0:28:84:0,84,1012 0/0:31,0:31:93:0,93,1145 0/0:38,0:38:96:0,96,1440 0/0:31,0:31:71:0,71,1254 0/0:47,0:47:99:0,120,1800 0/0:39,0:39:99:0,105,1575 0/0:36,0:36:99:0,105,1575 0/0:32,0:32:93:0,93,1395 0/0:39,0:39:90:0,90,1507 0/0:33,0:33:96:0,96,1353 0/0:40,0:40:99:0,111,1665 0/0:40,0:40:99:0,114,1710 0/0:45,0:45:99:0,120,1800 0/0:35,0:35:93:0,93,1395 0/0:22,0:22:66:0,66,830 0/0:20,0:20:60:0,60,665 0/0:20,0:20:60:0,60,685 0/0:49,0:49:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:33,0:33:90:0,90,1350 0/0:46,0:46:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:40,0:40:94:0,94,1579 0/0:39,0:39:99:0,114,1710 0/0:28,0:28:75:0,75,1125 0/0:35,0:35:99:0,102,1530 0/0:40,0:40:99:0,105,1575 0/0:31,0:31:81:0,81,1215 0/0:43,0:43:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:32,0:32:96:0,96,1307 0/0:47,0:47:99:0,120,1800 0/0:37,0:37:99:0,108,1498 0/0:33,0:33:99:0,99,1296 0/0:35,0:35:70:0,70,1323 0/0:20,0:20:60:0,60,735 0/0:42,0:42:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:44,0:44:99:0,120,1800 0/0:27,0:27:81:0,81,1101 0/0:43,0:43:99:0,120,1800 0/0:31,0:31:90:0,90,1350 0/0:39,0:39:99:0,102,1530 0/0:24,0:24:72:0,72,931 0/0:39,0:39:99:0,114,1710 0/0:45,0:45:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:38,0:38:99:0,111,1665 0/0:20,0:20:60:0,60,748 0/0:31,0:31:74:0,74,1074 0/0:48,0:48:99:0,108,1793 0/0:20,0:20:60:0,60,732 0/0:36,0:36:99:0,102,1530 0/0:21,0:21:60:0,60,900 0/0:35,0:35:99:0,102,1530 0/0:21,0:21:63:0,63,762 0/0:24,0:24:72:0,72,958 0/0:29,0:29:87:0,87,950 0/0:21,0:21:60:0,60,900 0/0:23,0:23:66:0,66,990 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:63:0,63,733 0/0:20,0:20:60:0,60,742 0/1:71,82:153:99:2306,0,2141 0/0:21,0:21:60:0,60,869 0/0:31,0:31:93:0,93,1279 0/0:28,0:28:72:0,72,1080 0/0:27,0:27:75:0,75,1125 0/0:37,0:37:98:0,98,1516 0/0:32,0:32:93:0,93,1287 0/0:21,0:21:63:0,63,736 0/0:22,0:22:60:0,60,900 0/0:23,0:23:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,705 0/0:21,0:21:60:0,60,900 0/0:21,0:21:63:0,63,871 0/0:22,0:22:62:0,62,945 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,762 +20 14032627 . A T 716.77 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=-0.336;AN=200;InbreedingCoeff=-0.0037;AF=0.001724;GQ_STDDEV=20.02;FS=5.799;DP=15505;GQ_MEAN=41.33;VQSLOD=2.03;ClippingRankSum=1.03;BaseQRankSum=2.44;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=15.25;MQRankSum=0.103;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:14,0:14:24:0,24,360 0/0:12,0:12:27:0,27,405 0/0:13,0:13:36:0,36,468 0/0:9,0:9:24:0,24,303 0/0:16,0:16:27:0,27,405 0/0:12,0:12:30:0,30,450 0/0:10,0:10:21:0,21,315 0/0:6,0:6:15:0,15,225 0/0:11,0:11:27:0,27,405 0/0:12,0:12:27:0,27,405 0/0:14,0:14:36:0,36,540 0/0:6,0:6:15:0,15,224 0/0:14,0:14:36:0,36,486 0/0:12,0:12:33:0,33,495 0/0:8,0:8:21:0,21,297 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,247 0/0:4,0:4:3:0,3,45 0/0:8,0:8:21:0,21,292 0/0:18,0:18:45:0,45,675 0/0:12,0:12:30:0,30,450 0/0:10,0:10:27:0,27,405 0/1:11,5:16:99:116,0,363 0/0:66,0:66:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:14,0:14:33:0,33,495 0/0:26,0:26:66:0,66,990 0/0:25,0:25:60:0,60,900 0/1:5,16:21:99:549,0,116 0/0:14,0:14:33:0,33,495 0/0:14,0:14:33:0,33,495 0/0:21,0:21:60:0,60,657 0/0:32,0:32:76:0,76,1157 0/0:36,0:36:78:0,78,1170 0/0:40,0:40:99:0,102,1530 0/0:19,0:19:45:0,45,675 0/0:23,0:23:60:0,60,877 0/0:9,0:9:21:0,21,315 0/0:16,0:16:36:0,36,540 0/0:15,0:15:33:0,33,495 0/0:16,0:16:31:0,31,540 0/0:22,0:22:60:0,60,740 0/0:23,0:23:60:0,60,900 0/0:20,0:20:42:0,42,630 0/0:24,0:24:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:14,0:14:39:0,39,585 0/0:17,0:17:48:0,48,669 0/0:21,0:21:60:0,60,821 0/0:12,0:12:26:0,26,462 0/0:20,0:20:60:0,60,683 0/0:15,0:15:39:0,39,585 0/0:25,0:25:60:0,60,900 0/0:20,0:20:48:0,48,720 0/0:17,0:17:48:0,48,720 0/0:14,0:14:33:0,33,495 0/0:25,0:25:63:0,63,935 0/0:27,0:27:60:0,60,900 0/0:18,0:18:42:0,42,630 0/0:16,0:16:36:0,36,612 0/0:35,0:35:70:0,70,1305 0/0:23,0:23:60:0,60,900 0/0:16,0:16:20:0,20,450 0/0:17,0:17:36:0,36,540 0/0:13,0:13:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:16,0:16:42:0,42,616 0/0:9,0:9:24:0,24,316 0/0:24,0:24:63:0,63,945 0/0:14,0:14:30:0,30,450 0/0:22,0:22:60:0,60,900 0/0:19,0:19:39:0,39,585 0/0:11,0:11:21:0,21,315 0/0:12,0:12:20:0,20,360 0/0:24,0:24:60:0,60,900 0/0:14,0:14:36:0,36,540 0/0:21,0:21:48:0,48,720 0/0:15,0:15:29:0,29,450 0/0:6,0:6:15:0,15,225 0/0:8,0:8:21:0,21,315 0/0:12,0:12:33:0,33,455 0/0:23,0:23:60:0,60,812 0/0:20,0:20:51:0,51,765 0/0:18,0:18:20:0,20,659 0/0:19,0:19:39:0,39,585 0/0:18,0:18:48:0,48,720 0/0:9,0:9:21:0,21,315 0/0:24,0:24:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:19,0:19:45:0,45,614 0/0:17,0:17:23:0,23,450 0/0:16,0:16:34:0,34,540 0/0:26,0:26:66:0,66,990 0/0:15,0:15:21:0,21,315 0/0:11,0:11:30:0,30,403 0/0:12,0:12:30:0,30,450 0/0:9,0:9:20:0,20,315 0/0:15,0:15:24:0,24,360 +20 14066228 . AT A 58.23 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.727;AN=196;InbreedingCoeff=-0.0472;AF=6.41E-4;GQ_STDDEV=11.82;FS=0.0;DP=4546;GQ_MEAN=16.37;VQSLOD=4.02;ClippingRankSum=0.727;BaseQRankSum=0.727;MLEAF=6.41E-4;MLEAC=1;MQ=60.0;QD=14.56;MQRankSum=-0.727;CCC=1560;NCC=90 GT:AD:DP:GQ:PL 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,257 0/0:8,0:8:24:0,24,303 0/0:7,0:7:21:0,21,249 0/0:7,0:7:21:0,21,285 0/0:8,0:8:21:0,21,315 0/0:8,0:8:24:0,24,305 0/0:9,0:9:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:9,0:9:27:0,27,313 0/0:7,0:7:15:0,15,225 0/0:3,0:3:9:0,9,107 0/0:9,0:9:24:0,24,360 0/0:5,0:5:9:0,9,135 0/0:16,0:16:36:0,36,540 0/0:10,0:10:21:0,21,315 0/0:7,0:7:21:0,21,232 0/0:7,0:7:21:0,21,266 0/0:11,0:11:33:0,33,419 0/0:10,0:10:30:0,30,349 0/0:16,0:16:45:0,45,582 0/0:7,0:7:21:0,21,254 0/0:21,0:21:60:0,60,900 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,258 0/0:8,0:8:24:0,24,293 0/0:1,0:1:3:0,3,29 0/0:2,0:2:6:0,6,69 0/0:1,0:1:3:0,3,27 0/0:7,0:7:21:0,21,263 0/0:3,0:3:9:0,9,105 0/0:2,0:2:6:0,6,70 0/0:3,0:3:6:0,6,90 0/0:7,0:7:21:0,21,239 0/0:8,0:8:21:0,21,315 0/0:13,0:13:39:0,39,470 0/0:3,0:3:6:0,6,90 0/0:10,0:10:21:0,21,315 0/0:2,0:2:6:0,6,75 0/0:9,0:9:21:0,21,315 0/0:4,0:4:9:0,9,135 0/0:3,0:3:9:0,9,108 0/0:7,0:7:21:0,21,262 0/0:7,0:7:21:0,21,236 0/0:2,0:2:6:0,6,75 0/0:3,0:3:9:0,9,110 0/0:8,0:8:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:3,0:3:9:0,9,112 0/0:3,0:3:9:0,9,115 0/0:10,0:10:27:0,27,362 0/0:3,0:3:9:0,9,106 0/0:7,0:7:21:0,21,242 0/0:2,0:2:6:0,6,74 0/0:8,0:8:24:0,24,258 0/0:4,0:4:9:0,9,135 0/0:4,0:4:9:0,9,135 0/0:2,0:2:6:0,6,76 0/0:3,0:3:9:0,9,113 0/0:4,0:4:12:0,12,146 0/0:2,0:2:6:0,6,68 0/0:3,0:3:9:0,9,86 0/0:2,0:2:6:0,6,72 0/0:20,0:20:60:0,60,738 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,75 0/0:8,0:8:21:0,21,315 0/0:3,0:3:9:0,9,112 0/0:12,0:12:30:0,30,450 0/0:7,0:7:21:0,21,252 0/0:7,0:7:21:0,21,239 0/0:7,0:7:21:0,21,268 0/0:7,0:7:21:0,21,254 0/0:2,0:2:6:0,6,69 0/0:7,0:7:21:0,21,251 0/0:4,0:4:9:0,9,135 0/0:7,0:7:21:0,21,271 0/0:2,0:2:6:0,6,72 0/0:7,0:7:21:0,21,275 0/0:7,0:7:21:0,21,282 0/0:3,0:3:9:0,9,105 0/0:3,0:3:9:0,9,113 0/0:2,0:2:6:0,6,63 0/0:7,0:7:21:0,21,242 0/0:9,0:9:27:0,27,345 0/0:9,0:9:27:0,27,318 0/0:9,0:9:27:0,27,333 0/0:2,0:2:6:0,6,71 0/0:8,0:8:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,72 0/0:12,0:12:30:0,30,439 0/0:7,0:7:21:0,21,255 0/1:1,3:4:27:107,0,27 0/0:8,0:8:21:0,21,315 0/0:4,0:4:9:0,9,135 0/0:7,0:7:21:0,21,250 +20 14066252 rs187016452 C A 113.51 PASS HWP=1.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=-0.573;AN=200;InbreedingCoeff=-0.0071;AF=0.001151;GQ_STDDEV=20.95;FS=0.0;DP=12608;GQ_MEAN=41.98;VQSLOD=2.33;ClippingRankSum=1.64;BaseQRankSum=-0.248;MLEAF=0.001151;MLEAC=2;MQ=60.0;QD=4.54;DB;MQRankSum=-0.573;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:20,0:20:60:0,60,711 0/0:20,0:20:60:0,60,682 0/0:8,0:8:24:0,24,303 0/0:7,0:7:21:0,21,249 0/0:20,0:20:60:0,60,729 0/0:20,0:20:60:0,60,699 0/0:22,0:22:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:24,0:24:69:0,69,989 0/0:22,0:22:63:0,63,945 0/0:7,0:7:21:0,21,266 0/0:7,0:7:21:0,21,261 0/0:25,0:25:50:0,50,905 0/0:21,0:21:63:0,63,742 0/0:22,0:22:60:0,60,799 0/0:20,0:20:60:0,60,690 0/0:22,0:22:60:0,60,900 0/0:23,0:23:69:0,69,807 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,718 0/0:25,0:25:63:0,63,945 0/0:22,0:22:63:0,63,814 0/0:21,0:21:60:0,60,900 0/0:8,0:8:24:0,24,299 0/0:7,0:7:21:0,21,266 0/0:8,0:8:21:0,21,315 0/0:20,0:20:60:0,60,734 0/0:20,0:20:60:0,60,723 0/0:7,0:7:21:0,21,252 0/0:7,0:7:21:0,21,245 0/0:2,0:2:6:0,6,64 0/0:22,0:22:63:0,63,804 0/0:21,0:21:60:0,60,745 0/0:21,0:21:63:0,63,731 0/0:20,0:20:60:0,60,718 0/0:20,0:20:60:0,60,714 0/0:20,0:20:60:0,60,680 0/0:22,0:22:63:0,63,945 0/0:8,0:8:21:0,21,315 0/0:20,0:20:60:0,60,706 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,220 0/0:8,0:8:24:0,24,293 0/0:20,0:20:60:0,60,745 0/0:22,0:22:66:0,66,748 0/0:8,0:8:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,683 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,253 0/0:20,0:20:60:0,60,772 0/0:21,0:21:60:0,60,821 0/0:21,0:21:60:0,60,785 0/0:20,0:20:60:0,60,694 0/0:20,0:20:60:0,60,691 0/0:22,0:22:60:0,60,769 0/0:20,0:20:60:0,60,727 0/0:22,0:22:63:0,63,811 0/0:7,0:7:21:0,21,251 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,716 0/0:20,0:20:60:0,60,698 0/0:7,0:7:21:0,21,227 0/0:7,0:7:21:0,21,235 0/0:20,0:20:60:0,60,738 0/0:20,0:20:60:0,60,703 0/0:7,0:7:21:0,21,240 0/0:24,0:24:60:0,60,870 0/0:20,0:20:60:0,60,696 0/0:22,0:22:66:0,66,768 0/0:20,0:20:60:0,60,766 0/0:23,0:23:60:0,60,818 0/0:22,0:22:63:0,63,839 0/0:21,0:21:60:0,60,802 0/0:8,0:8:24:0,24,290 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,737 0/0:22,0:22:66:0,66,784 0/0:20,0:20:60:0,60,693 0/0:7,0:7:21:0,21,275 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,252 0/0:20,0:20:60:0,60,688 0/0:22,0:22:60:0,60,768 0/0:20,0:20:60:0,60,865 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,845 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,789 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,830 0/0:8,0:8:21:0,21,285 0/0:22,0:22:60:0,60,900 0/0:7,0:7:21:0,21,255 0/1:6,3:9:89:89,0,190 0/0:28,0:28:57:0,57,984 0/0:7,0:7:21:0,21,250 0/0:20,0:20:60:0,60,664 +20 14066276 rs2990505 C T 231570.00 PASS HWP=0.5689;AC=44;culprit=MQ;MQ0=0;ReadPosRankSum=0.269;AN=200;InbreedingCoeff=0.0198;AF=0.257;GQ_STDDEV=240.64;FS=0.772;DP=24100;GQ_MEAN=208.14;POSITIVE_TRAIN_SITE;VQSLOD=5.34;ClippingRankSum=-0.151;BaseQRankSum=-2.279;MLEAF=0.257;MLEAC=447;MQ=60.0;QD=15.96;DB;MQRankSum=0.132;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:20,0:20:60:0,60,711 0/0:20,0:20:60:0,60,682 0/0:21,0:21:60:0,60,808 0/0:21,0:21:60:0,60,784 0/1:29,16:45:99:476,0,929 0/0:20,0:20:60:0,60,699 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,787 0/0:24,0:24:69:0,69,989 0/0:22,0:22:63:0,63,945 0/1:20,11:31:99:330,0,644 0/0:7,0:7:21:0,21,261 0/1:15,21:36:99:669,0,441 0/1:21,22:43:99:664,0,619 0/1:14,15:29:99:433,0,443 0/1:22,28:50:99:821,0,610 0/1:27,17:44:99:432,0,769 0/1:29,17:46:99:440,0,904 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,718 1/1:0,28:28:84:999,84,0 0/1:17,18:35:99:547,0,484 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,840 0/0:20,0:20:60:0,60,719 1/1:0,30:30:90:1079,90,0 0/0:20,0:20:60:0,60,734 0/0:20,0:20:60:0,60,723 0/0:20,0:20:60:0,60,710 0/0:20,0:20:60:0,60,656 0/0:8,0:8:21:0,21,315 0/0:22,0:22:63:0,63,804 0/1:34,26:60:99:641,0,1101 0/0:21,0:21:63:0,63,731 0/1:31,36:67:99:1067,0,1018 0/1:30,14:44:99:365,0,910 0/1:24,22:46:99:601,0,821 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,743 0/0:20,0:20:60:0,60,706 0/1:13,12:25:99:324,0,366 1/1:0,29:29:87:1022,87,0 0/1:25,17:42:99:491,0,753 0/1:17,19:36:99:573,0,508 0/0:20,0:20:60:0,60,745 0/1:24,32:56:99:985,0,658 0/0:21,0:21:63:0,63,758 0/0:21,0:21:60:0,60,900 0/1:32,18:50:99:527,0,977 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,782 0/0:20,0:20:60:0,60,772 0/1:25,13:38:99:344,0,730 0/0:21,0:21:60:0,60,785 0/1:33,30:63:99:882,0,1069 0/0:20,0:20:60:0,60,691 0/0:22,0:22:60:0,60,769 0/1:26,22:48:99:682,0,775 0/1:24,22:46:99:613,0,767 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,716 0/0:20,0:20:60:0,60,698 0/0:22,0:22:60:0,60,848 0/1:15,13:28:99:394,0,446 0/1:20,29:49:99:859,0,607 0/0:20,0:20:60:0,60,703 0/1:17,9:26:99:252,0,568 0/0:24,0:24:60:0,60,870 0/0:20,0:20:60:0,60,696 0/0:22,0:22:66:0,66,768 1/1:1,35:36:71:1190,71,0 0/0:23,0:23:60:0,60,818 0/0:22,0:22:63:0,63,839 0/0:21,0:21:60:0,60,802 0/0:20,0:20:60:0,60,754 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,737 1/1:0,52:52:99:1818,156,0 0/0:20,0:20:60:0,60,693 0/1:18,16:34:99:405,0,539 0/0:20,0:20:60:0,60,709 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,688 0/0:22,0:22:60:0,60,768 0/0:20,0:20:60:0,60,865 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,845 0/1:19,18:37:99:466,0,498 0/1:18,30:48:99:895,0,540 0/0:21,0:21:60:0,60,789 0/1:22,26:48:99:810,0,645 0/1:13,28:41:99:868,0,362 0/0:23,0:23:66:0,66,990 0/0:22,0:22:60:0,60,900 1/1:0,29:29:87:969,87,0 0/1:6,14:20:99:416,0,150 0/0:27,0:27:60:0,60,900 0/1:7,14:21:99:421,0,232 0/0:20,0:20:60:0,60,664 +20 14306773 rs35253731 T G 141643.00 PASS HWP=0.1158;AC=12;culprit=FS;MQ0=0;ReadPosRankSum=0.656;AN=200;InbreedingCoeff=0.0639;AF=0.071;GQ_STDDEV=371.15;FS=0.0;DP=57095;GQ_MEAN=225.38;POSITIVE_TRAIN_SITE;VQSLOD=6.62;ClippingRankSum=0.206;BaseQRankSum=3.67;MLEAF=0.071;MLEAC=123;MQ=59.7;QD=15.79;DB;MQRankSum=0.348;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:87,0:87:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:30,0:30:63:0,63,945 0/0:88,0:88:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:82,0:82:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:73,0:73:99:0,120,1800 0/0:29,0:29:60:0,60,900 0/1:28,34:62:99:1094,0,819 0/0:29,0:29:63:0,63,945 0/0:55,0:55:99:0,120,1800 1/1:0,72:72:99:2649,217,0 0/1:34,29:63:99:869,0,973 0/0:57,0:57:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/1:38,37:75:99:1170,0,1188 0/0:88,0:88:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:51,0:51:99:0,120,1800 1/1:0,73:73:99:2705,219,0 0/0:132,0:132:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:151,0:151:99:0,120,1800 0/1:20,27:47:99:747,0,501 0/0:60,0:60:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:111,0:111:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/1:71,50:121:99:1590,0,2218 0/0:91,0:91:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:102,0:102:99:0,120,1800 0/0:102,0:102:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:116,0:116:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:151,0:151:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:39,0:39:84:0,84,1405 0/0:116,0:116:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:121,0:121:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/1:31,39:70:99:1377,0,898 0/0:68,0:68:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:46,0:46:99:0,107,1665 0/1:38,31:69:99:1048,0,1201 0/1:45,45:90:99:1547,0,1407 0/0:60,0:60:99:0,120,1800 0/0:30,0:30:63:0,63,945 0/0:59,0:59:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:125,0:125:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:58,0:58:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:41,0:41:87:0,87,1574 0/0:62,0:62:99:0,120,1800 +20 14306896 rs6042672 G A 1877620.00 PASS HWP=0.0238;AC=58;culprit=QD;MQ0=0;ReadPosRankSum=0.615;AN=200;InbreedingCoeff=0.0787;AF=0.368;GQ_STDDEV=1338.43;FS=2.018;DP=119220;GQ_MEAN=1265.12;POSITIVE_TRAIN_SITE;VQSLOD=5.03;ClippingRankSum=-0.355;BaseQRankSum=-3.915;MLEAF=0.368;MLEAC=641;MQ=59.64;QD=19.04;DB;MQRankSum=0.152;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:96,99:195:99:2876,0,2935 0/1:99,106:205:99:3076,0,3167 0/0:54,0:54:99:0,120,1800 0/0:30,0:30:63:0,63,945 0/0:88,0:88:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/1:116,119:235:99:3760,0,3697 0/1:75,107:182:99:3063,0,2301 0/0:84,0:84:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:82,0:82:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:57,61:118:99:1812,0,1635 0/0:29,0:29:60:0,60,900 0/1:55,55:110:99:1588,0,1662 0/0:29,0:29:63:0,63,945 0/0:55,0:55:99:0,120,1800 1/1:0,179:179:99:6162,538,0 1/1:0,132:132:99:4699,397,0 0/1:84,87:171:99:2509,0,2606 0/1:77,82:159:99:2371,0,2266 0/0:100,0:100:99:0,120,1800 0/0:95,0:95:99:0,120,1800 1/1:0,207:207:99:7485,622,0 0/0:88,0:88:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/1:112,99:211:99:2969,0,3716 0/1:107,91:198:99:2750,0,3387 0/0:51,0:51:99:0,120,1800 1/1:2,172:174:99:5975,435,0 0/1:150,112:262:99:3214,0,5297 0/0:40,0:40:84:0,84,1260 0/0:151,0:151:99:0,120,1800 0/1:106,97:203:99:2479,0,3166 0/1:130,86:216:99:2319,0,3925 1/1:0,159:159:99:5606,478,0 0/0:82,0:82:99:0,120,1800 0/0:111,0:111:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/1:87,93:180:99:2926,0,2653 0/0:60,0:60:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/1:118,104:222:99:3139,0,3829 0/1:124,115:239:99:3330,0,3902 0/1:92,119:211:99:3888,0,2937 0/0:102,0:102:99:0,120,1800 0/1:144,121:265:99:3902,0,4869 1/1:0,266:266:99:9896,800,0 0/0:84,0:84:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/1:125,111:236:99:3243,0,3799 0/0:106,0:106:99:0,120,1800 0/1:130,109:239:99:3386,0,4275 0/0:94,0:94:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/1:113,113:226:99:3460,0,3639 0/0:78,0:78:99:0,120,1800 0/0:151,0:151:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/1:91,101:192:99:3255,0,2834 1/1:0,167:167:99:6021,502,0 0/0:37,0:37:90:0,90,1350 0/0:39,0:39:84:0,84,1405 0/1:129,160:289:99:5076,0,4431 0/0:52,0:52:99:0,120,1800 0/1:125,126:251:99:3903,0,4273 0/1:129,88:217:99:2692,0,4537 0/1:176,140:316:99:4238,0,5497 0/1:80,93:173:99:2776,0,2602 0/0:71,0:71:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/1:109,86:195:99:2472,0,3712 1/1:0,214:214:99:7989,643,0 0/0:73,0:73:99:0,120,1800 0/1:99,72:171:99:2020,0,3501 0/1:77,63:140:99:1934,0,2431 1/1:3,167:170:99:5987,384,0 0/1:104,118:222:99:3749,0,3458 0/1:124,115:239:99:3663,0,4048 0/0:30,0:30:63:0,63,945 0/1:104,109:213:99:3056,0,2982 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:125,0:125:99:0,120,1800 0/1:136,116:252:99:3298,0,4088 0/0:55,0:55:99:0,120,1800 0/1:127,111:238:99:3398,0,4295 0/1:93,91:184:99:2887,0,3164 0/1:125,111:236:99:3194,0,3915 0/0:29,0:29:66:0,66,990 0/1:103,71:174:99:2002,0,3628 0/0:68,0:68:99:0,120,1800 0/1:91,69:160:99:2145,0,2904 0/1:144,103:247:99:3017,0,4707 +20 14306953 rs6079391 G T 1559680.00 PASS HWP=0.0692;AC=79;culprit=FS;MQ0=0;ReadPosRankSum=0.675;AN=200;InbreedingCoeff=0.0647;AF=0.241;GQ_STDDEV=1648.64;FS=0.521;DP=113184;GQ_MEAN=1248.82;POSITIVE_TRAIN_SITE;VQSLOD=5.97;ClippingRankSum=-0.597;BaseQRankSum=-4.101;MLEAF=0.241;MLEAC=420;MQ=59.68;QD=16.61;DB;MQRankSum=0.404;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:161,123:284:99:3295,0,4605 0/1:156,137:293:99:3863,0,4395 0/1:149,143:292:99:4005,0,4213 0/0:30,0:30:63:0,63,945 0/1:173,133:306:99:3742,0,4878 0/1:189,151:340:99:4120,0,5328 0/1:191,144:335:99:4067,0,5585 0/1:164,108:272:99:2805,0,4511 0/1:168,135:303:99:3865,0,5021 0/0:28,0:28:60:0,60,900 0/1:135,138:273:99:4047,0,4259 0/1:128,105:233:99:2928,0,3471 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:88,0:88:99:0,120,1800 0/0:29,0:29:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:29,0:29:63:0,63,945 1/1:0,190:190:99:6333,570,0 0/0:27,0:27:62:0,62,990 0/0:31,0:31:63:0,63,945 0/1:136,130:266:99:3447,0,3927 0/1:119,108:227:99:3019,0,3489 1/1:2,343:345:99:12573,1031,0 1/1:1,325:326:99:11694,969,0 0/0:27,0:27:60:0,60,900 1/1:0,283:283:99:9842,850,0 1/1:0,277:277:99:9709,832,0 0/1:153,137:290:99:3734,0,4758 0/1:132,141:273:99:3688,0,3903 0/1:132,114:246:99:2988,0,3784 0/0:25,0:25:60:0,60,900 0/1:166,154:320:99:4551,0,5121 0/0:40,0:40:84:0,84,1260 0/1:156,167:323:99:4958,0,4646 0/0:34,0:34:60:0,60,900 0/0:207,0:207:99:0,120,1800 0/0:23,0:23:60:0,60,900 1/1:1,266:267:99:9209,793,0 0/1:151,138:289:99:4090,0,4440 1/1:0,210:210:99:7409,631,0 0/0:23,0:23:60:0,60,876 0/1:164,133:297:99:3741,0,4935 0/1:177,135:312:99:3889,0,5558 0/0:32,0:32:72:0,72,1080 0/1:157,155:312:99:4585,0,4766 0/1:133,115:248:99:3417,0,4284 0/1:154,161:315:99:4782,0,4678 0/1:174,156:330:99:4726,0,5838 0/0:84,0:84:99:0,120,1800 0/1:144,127:271:99:3663,0,4478 0/1:138,138:276:99:4132,0,4266 0/1:163,100:263:99:2843,0,4743 1/1:0,350:350:99:11875,1051,0 0/1:182,157:339:99:4445,0,5551 0/0:25,0:25:66:0,66,990 1/1:0,296:296:99:10528,889,0 0/0:53,0:53:99:0,120,1800 0/1:173,143:316:99:4209,0,5096 1/1:0,321:321:99:11719,968,0 0/1:156,108:264:99:3084,0,4832 0/1:146,161:307:99:4696,0,4500 1/1:0,341:341:99:12278,1026,0 0/1:152,132:284:99:3630,0,4677 0/1:148,127:275:99:3531,0,4538 0/0:149,0:149:99:0,120,1800 1/1:0,202:202:99:7065,607,0 0/1:89,103:192:99:2714,0,2797 0/1:175,167:342:99:4988,0,5640 1/1:1,238:239:99:8087,674,0 0/1:190,129:319:99:3872,0,5672 0/0:28,0:28:72:0,72,1125 0/0:35,0:35:63:0,63,945 0/1:131,127:258:99:3584,0,3684 1/1:1,298:299:99:10492,895,0 1/1:0,235:235:99:7991,706,0 1/1:0,320:320:99:11006,962,0 0/1:148,134:282:99:3987,0,4547 0/0:25,0:25:60:0,60,900 1/1:0,298:298:99:10296,896,0 0/0:27,0:27:60:0,60,900 0/1:100,81:181:99:2408,0,2922 0/0:26,0:26:60:0,60,900 0/1:167,136:303:99:3893,0,5428 0/1:155,150:305:99:4188,0,4697 0/0:30,0:30:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:184,161:345:99:4639,0,6063 0/0:35,0:35:60:0,60,900 0/1:183,171:354:99:4517,0,5161 0/0:25,0:25:60:0,60,900 0/1:102,109:211:99:3093,0,3236 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:31,0:31:65:0,65,990 0/1:163,145:308:99:4147,0,5081 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 +20 14307019 rs36034779 T G 30424.90 PASS HWP=1.0;AC=3;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.047;AN=200;InbreedingCoeff=-0.0064;AF=0.006322;GQ_STDDEV=326.99;FS=1.907;DP=34135;GQ_MEAN=103.13;POSITIVE_TRAIN_SITE;VQSLOD=4.17;ClippingRankSum=1.11;BaseQRankSum=-0.229;MLEAF=0.006322;MLEAC=11;MQ=59.81;QD=14.45;DB;MQRankSum=0.328;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:32,0:32:69:0,69,1035 0/0:34,0:34:66:0,66,1199 0/0:29,0:29:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:88,0:88:99:0,120,1800 0/0:29,0:29:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:27,0:27:62:0,62,990 0/0:31,0:31:63:0,63,945 0/1:88,84:172:99:2485,0,2680 0/0:58,0:58:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:47,0:47:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:25,0:25:60:0,60,900 0/1:128,123:251:99:3785,0,4142 0/0:40,0:40:84:0,84,1260 0/0:42,0:42:69:0,69,1575 0/0:34,0:34:60:0,60,900 0/0:207,0:207:99:0,120,1800 0/0:23,0:23:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:46,0:46:99:0,114,1710 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,876 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:51,0:51:99:0,114,1710 0/0:33,0:33:75:0,75,1125 0/0:33,0:33:84:0,84,1260 0/0:292,0:292:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:38,0:38:93:0,93,1395 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:50,0:50:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:30,0:30:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:69:0,69,1035 0/0:33,0:33:75:0,75,1125 0/1:151,152:303:99:4920,0,4804 0/0:30,0:30:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:149,0:149:99:0,120,1800 0/0:28,0:28:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:33,0:33:81:0,81,1215 0/0:28,0:28:66:0,66,990 0/0:24,0:24:61:0,61,990 0/0:28,0:28:72:0,72,1125 0/0:35,0:35:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:81:0,81,1215 0/0:30,0:30:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:61:0,61,1035 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:39,0:39:84:0,84,1260 0/0:35,0:35:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:31,0:31:65:0,65,990 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 +20 14307024 rs8120693 C T 71649.80 PASS HWP=1.0;AC=4;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.285;AN=200;InbreedingCoeff=-0.0164;AF=0.016;GQ_STDDEV=454.24;FS=1.169;DP=32472;GQ_MEAN=147.02;POSITIVE_TRAIN_SITE;VQSLOD=5.26;ClippingRankSum=0.197;BaseQRankSum=-7.144;MLEAF=0.016;MLEAC=28;MQ=59.68;QD=13.74;DB;MQRankSum=0.27;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:32,0:32:69:0,69,1035 0/0:34,0:34:66:0,66,1199 0/0:29,0:29:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:33,55:88:99:1672,0,994 0/0:29,0:29:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:27,0:27:62:0,62,990 0/0:31,0:31:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:58,0:58:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:47,0:47:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:33,0:33:78:0,78,1170 0/0:40,0:40:84:0,84,1260 0/0:42,0:42:69:0,69,1575 0/0:34,0:34:60:0,60,900 0/1:117,88:205:99:2347,0,3665 0/0:23,0:23:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:46,0:46:99:0,114,1710 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,876 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:51,0:51:99:0,114,1710 0/0:33,0:33:75:0,75,1125 0/0:33,0:33:84:0,84,1260 0/1:149,139:288:99:4125,0,5373 0/0:84,0:84:99:0,120,1800 0/0:38,0:38:93:0,93,1395 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:50,0:50:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:30,0:30:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:69:0,69,1035 0/0:33,0:33:75:0,75,1125 0/0:45,0:45:99:0,117,1755 0/0:30,0:30:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/1:74,73:147:99:2196,0,2290 0/0:28,0:28:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:33,0:33:81:0,81,1215 0/0:28,0:28:66:0,66,990 0/0:24,0:24:61:0,61,990 0/0:28,0:28:72:0,72,1125 0/0:35,0:35:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:81:0,81,1215 0/0:30,0:30:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:61:0,61,1035 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:39,0:39:84:0,84,1260 0/0:35,0:35:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:31,0:31:65:0,65,990 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 +20 14307322 rs149124349 A G 2658.32 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.398;AN=200;InbreedingCoeff=-0.0023;AF=0.002299;GQ_STDDEV=45.42;FS=2.582;DP=26047;GQ_MEAN=69.6;POSITIVE_TRAIN_SITE;VQSLOD=4.45;ClippingRankSum=-0.424;BaseQRankSum=2.62;MLEAF=0.002299;MLEAC=4;MQ=60.0;QD=14.69;DB;MQRankSum=0.278;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:32,0:32:69:0,69,1035 0/0:34,0:34:66:0,66,1199 0/0:29,0:29:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:65:0,65,986 0/0:29,0:29:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:27,0:27:62:0,62,990 0/0:31,0:31:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:58,0:58:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:47,0:47:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:63,0:63:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:33,0:33:78:0,78,1170 0/0:40,0:40:84:0,84,1260 0/0:42,0:42:69:0,69,1575 0/0:34,0:34:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:46,0:46:99:0,114,1710 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,876 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:51,0:51:99:0,114,1710 0/0:33,0:33:75:0,75,1125 0/0:33,0:33:84:0,84,1260 0/0:28,0:28:66:0,66,990 0/1:47,39:86:99:1292,0,1298 0/0:38,0:38:93:0,93,1395 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:50,0:50:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:30,0:30:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:69:0,69,1035 0/0:33,0:33:75:0,75,1125 0/0:45,0:45:99:0,117,1755 0/0:30,0:30:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:33,0:33:81:0,81,1215 0/0:28,0:28:66:0,66,990 0/0:24,0:24:61:0,61,990 0/0:28,0:28:72:0,72,1125 0/0:35,0:35:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:81:0,81,1215 0/0:30,0:30:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:61:0,61,1035 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:39,0:39:84:0,84,1260 0/0:35,0:35:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:31,0:31:65:0,65,990 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 +20 14308080 . A G 2378.31 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=-0.67;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=56.33;FS=0.0;DP=25675;GQ_MEAN=69.32;VQSLOD=3.73;ClippingRankSum=0.795;BaseQRankSum=6.13;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=14.33;MQRankSum=0.499;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:32,0:32:69:0,69,1035 0/0:34,0:34:66:0,66,1199 0/0:29,0:29:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:65:0,65,986 0/0:29,0:29:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:27,0:27:62:0,62,990 0/0:31,0:31:63:0,63,945 0/0:26,0:26:60:0,60,900 0/1:27,31:58:99:927,0,769 0/0:28,0:28:60:0,60,900 0/0:47,0:47:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:34,0:34:63:0,63,945 0/1:60,48:108:99:1528,0,1744 0/0:27,0:27:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:33,0:33:78:0,78,1170 0/0:40,0:40:84:0,84,1260 0/0:42,0:42:69:0,69,1575 0/0:34,0:34:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:46,0:46:99:0,114,1710 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,876 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:51,0:51:99:0,114,1710 0/0:33,0:33:75:0,75,1125 0/0:33,0:33:84:0,84,1260 0/0:28,0:28:66:0,66,990 0/0:31,0:31:75:0,75,1125 0/0:38,0:38:93:0,93,1395 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:50,0:50:99:0,99,1485 0/0:53,0:53:99:0,120,1800 0/0:30,0:30:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:69:0,69,1035 0/0:33,0:33:75:0,75,1125 0/0:45,0:45:99:0,117,1755 0/0:30,0:30:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:33,0:33:81:0,81,1215 0/0:27,0:27:69:0,69,1035 0/0:24,0:24:61:0,61,990 0/0:28,0:28:72:0,72,1125 0/0:35,0:35:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:81:0,81,1215 0/0:30,0:30:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:61:0,61,1035 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:39,0:39:84:0,84,1260 0/0:35,0:35:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:31,0:31:65:0,65,990 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 +20 14830596 rs6079581 C G 198301.00 PASS HWP=0.3944;AC=69;culprit=MQ;MQ0=0;ReadPosRankSum=0.259;AN=200;InbreedingCoeff=0.0268;AF=0.262;GQ_STDDEV=197.0;FS=0.522;DP=22288;GQ_MEAN=179.4;POSITIVE_TRAIN_SITE;VQSLOD=5.2;ClippingRankSum=-0.07;BaseQRankSum=1.32;MLEAF=0.263;MLEAC=458;MQ=60.0;QD=17.37;DB;MQRankSum=0.199;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:7,0:7:21:0,21,267 0/0:27,0:27:60:0,60,900 0/0:9,0:9:24:0,24,322 0/1:6,6:12:99:143,0,181 0/0:14,0:14:0:0,0,360 0/1:19,11:30:99:359,0,587 0/0:7,0:7:21:0,21,292 0/0:13,0:13:30:0,30,450 0/0:8,0:8:21:0,21,315 0/1:4,6:10:99:212,0,127 0/1:4,10:14:99:387,0,126 0/1:8,3:11:88:88,0,242 0/1:19,18:37:99:619,0,552 1/1:0,20:20:60:692,60,0 0/0:14,0:14:36:0,36,525 0/1:23,13:36:99:353,0,713 0/0:21,0:21:60:0,60,900 1/1:0,19:19:57:691,57,0 0/1:12,7:19:99:223,0,401 0/0:29,0:29:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,877 0/1:40,32:72:99:961,0,999 0/0:35,0:35:99:0,102,1489 0/0:21,0:21:60:0,60,900 0/1:21,19:40:99:586,0,693 0/0:23,0:23:66:0,66,786 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,749 0/0:13,0:13:21:0,21,457 0/0:20,0:20:60:0,60,691 0/0:33,0:33:93:0,93,1395 0/1:30,22:52:99:756,0,1054 0/1:22,20:42:99:732,0,754 0/0:21,0:21:60:0,60,662 0/0:7,0:7:21:0,21,264 0/0:23,0:23:60:0,60,900 0/1:13,15:28:99:431,0,352 0/1:17,22:39:99:761,0,508 0/0:25,0:25:63:0,63,945 1/1:0,25:25:75:912,75,0 0/1:14,17:31:99:538,0,457 0/0:21,0:21:60:0,60,900 1/1:0,23:23:69:840,69,0 0/1:21,23:44:99:742,0,639 1/1:0,24:24:72:980,72,0 0/0:37,0:37:84:0,84,1260 0/1:18,19:37:99:669,0,597 1/1:0,42:42:99:1768,126,0 0/0:25,0:25:60:0,60,900 0/1:8,9:17:99:316,0,281 0/0:21,0:21:60:0,60,754 0/1:14,13:27:99:447,0,497 0/0:22,0:22:60:0,60,846 0/0:22,0:22:63:0,63,818 0/0:35,0:35:56:0,56,1215 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 1/1:0,29:29:87:1211,87,0 0/1:18,15:33:99:455,0,593 1/1:0,20:20:60:737,60,0 0/1:39,24:63:99:849,0,1287 0/1:18,9:27:99:252,0,601 1/1:0,29:29:87:1174,87,0 1/1:0,27:27:81:1048,81,0 0/1:9,4:13:99:141,0,338 0/0:9,0:9:20:0,20,321 0/1:21,15:36:99:531,0,770 0/1:12,11:23:99:411,0,370 0/1:15,20:35:99:641,0,479 1/1:0,21:21:63:859,63,0 0/1:27,17:44:99:610,0,914 0/0:22,0:22:60:0,60,900 1/1:0,24:24:72:990,72,0 1/1:0,18:18:54:742,54,0 1/1:0,21:21:63:921,63,0 0/1:4,8:12:99:251,0,118 0/0:23,0:23:60:0,60,900 0/1:17,11:28:99:379,0,506 0/1:13,5:18:99:161,0,507 0/1:14,9:23:99:315,0,409 1/1:0,14:14:42:564,42,0 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:66:0,66,908 0/1:7,13:20:99:396,0,242 0/0:28,0:28:44:0,44,826 0/1:13,7:20:99:210,0,375 0/1:28,19:47:99:662,0,941 0/0:22,0:22:60:0,60,900 0/1:12,9:21:99:270,0,351 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:15,0:15:33:0,33,495 0/1:10,14:24:99:539,0,345 0/1:11,12:23:99:413,0,371 0/1:11,13:24:99:422,0,354 0/1:17,13:30:99:483,0,460 +20 15866365 rs13045800 A G 143810.00 PASS HWP=0.1634;AC=16;culprit=FS;MQ0=0;ReadPosRankSum=0.613;AN=200;InbreedingCoeff=0.0543;AF=0.095;GQ_STDDEV=280.62;FS=0.0;DP=45135;GQ_MEAN=210.26;POSITIVE_TRAIN_SITE;VQSLOD=7.11;ClippingRankSum=-0.2;BaseQRankSum=-4.199;MLEAF=0.095;MLEAC=166;MQ=59.91;QD=15.89;DB;MQRankSum=0.418;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:48,0:48:99:0,120,1800 0/1:21,20:41:99:577,0,674 0/0:42,0:42:96:0,96,1552 0/0:51,0:51:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:45,0:45:99:0,108,1800 0/0:75,0:75:99:0,120,1800 0/1:22,31:53:99:883,0,693 0/0:54,0:54:99:0,120,1800 0/0:39,0:39:98:0,98,1558 0/0:60,0:60:99:0,120,1800 0/0:38,0:38:75:0,75,1326 1/1:0,72:72:99:2595,217,0 0/1:19,30:49:99:877,0,587 0/0:53,0:53:99:0,120,1800 1/1:0,73:73:99:2487,220,0 0/0:41,0:41:99:0,103,1606 0/1:34,40:74:99:1167,0,1035 0/0:52,0:52:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:59,0:59:99:0,102,1530 0/0:39,0:39:77:0,77,1350 0/0:62,0:62:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/1:29,43:72:99:1295,0,826 0/0:67,0:67:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:41,0:41:99:0,111,1681 0/1:49,43:92:99:1188,0,1607 0/0:60,0:60:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:29,0:29:69:0,69,1035 0/0:51,0:51:99:0,120,1800 0/0:45,0:45:99:0,117,1755 0/0:55,0:55:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:18,28:46:99:734,0,493 0/0:55,0:55:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:30,0:30:83:0,83,1260 0/0:33,0:33:90:0,90,1350 0/0:60,0:60:99:0,120,1800 0/0:37,0:37:97:0,97,1485 0/0:83,0:83:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:38,0:38:99:0,99,1485 0/0:39,0:39:99:0,114,1710 0/0:47,0:47:99:0,120,1800 0/0:44,0:44:99:0,116,1800 0/0:53,0:53:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:33,0:33:96:0,96,1252 0/0:34,0:34:90:0,90,1350 0/0:34,0:34:78:0,78,1440 0/0:48,0:48:99:0,117,1800 0/0:71,0:71:99:0,120,1800 0/1:22,24:46:99:715,0,729 0/1:23,17:40:99:509,0,727 0/0:57,0:57:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:26,0:26:75:0,75,1115 0/0:27,0:27:75:0,75,1125 0/0:47,0:47:99:0,114,1710 0/0:35,0:35:99:0,99,1485 0/0:48,0:48:99:0,114,1710 0/1:8,13:21:99:401,0,245 0/0:34,0:34:78:0,78,1170 0/0:45,0:45:99:0,116,1677 0/1:17,19:36:99:562,0,515 0/1:23,30:53:99:945,0,701 +20 15874325 rs932501 A G 1740.28 PASS HWP=0.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=-0.358;AN=30;InbreedingCoeff=0.2035;AF=0.151;GQ_STDDEV=16.93;FS=0.0;DP=313;GQ_MEAN=9.95;POSITIVE_TRAIN_SITE;VQSLOD=5.8;ClippingRankSum=0.731;BaseQRankSum=0.727;MLEAF=0.188;MLEAC=35;MQ=60.0;QD=21.48;DB;MQRankSum=0.358;CCC=186;NCC=777 GT:AD:DP:GQ:PL ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:1,0:1:3:0,3,41 ./.:2,0:2:.:. 0/0:4,0:4:0:0,0,26 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,70 0/0:2,0:2:6:0,6,73 ./.:0,0:0:.:. ./.:3,0:3:.:. 0/0:1,0:1:3:0,3,37 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 0/0:4,0:4:0:0,0,70 0/0:2,0:2:6:0,6,84 0/1:1,3:4:25:78,0,25 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,61 ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:3,0:3:0:0,0,9 ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:7,0:7:0:0,0,134 ./.:0,0:0:.:. 0/0:1,0:1:3:0,3,31 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 15874488 rs6135591 G A 1018.02 PASS HWP=0.0264;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.358;AN=40;InbreedingCoeff=-0.023;AF=0.037;GQ_STDDEV=13.28;FS=0.0;DP=512;GQ_MEAN=8.75;POSITIVE_TRAIN_SITE;VQSLOD=6.27;ClippingRankSum=0.361;BaseQRankSum=0.736;MLEAF=0.046;MLEAC=15;MQ=60.0;QD=17.55;DB;MQRankSum=0.406;CCC=328;NCC=706 GT:AD:DP:GQ:PL ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,49 ./.:2,0:2:.:. 0/0:2,0:2:6:0,6,52 0/0:2,0:2:6:0,6,57 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,75 0/0:2,0:2:6:0,6,72 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. 0/0:1,0:1:3:0,3,26 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,70 0/0:2,0:2:6:0,6,73 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:3,0:3:6:0,6,90 0/1:2,4:6:63:105,0,63 0/0:2,0:2:3:0,3,45 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,65 0/0:4,0:4:0:0,0,83 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 ./.:0,0:0:.:. 0/0:7,0:7:21:0,21,211 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,54 0/0:2,0:2:6:0,6,65 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 15918077 rs149042547 C T 3445.32 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.748;AN=200;InbreedingCoeff=-0.0023;AF=0.002299;GQ_STDDEV=59.47;FS=6.866;DP=40059;GQ_MEAN=99.16;POSITIVE_TRAIN_SITE;VQSLOD=2.75;ClippingRankSum=-0.288;BaseQRankSum=-2.759;MLEAF=0.002299;MLEAC=4;MQ=60.0;QD=17.23;DB;MQRankSum=0.148;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:44,0:44:93:0,93,1395 0/0:36,0:36:93:0,93,1395 0/0:31,0:31:78:0,78,1204 0/0:46,0:46:99:0,120,1800 0/0:39,0:39:95:0,95,1657 0/0:50,0:50:99:0,120,1800 0/0:51,0:51:99:0,105,1575 0/0:37,0:37:84:0,84,1260 0/0:36,0:36:84:0,84,1260 0/0:32,0:32:66:0,66,1117 0/0:34,0:34:93:0,93,1395 0/0:27,0:27:64:0,64,945 0/0:58,0:58:99:0,120,1800 0/0:41,0:41:90:0,90,1350 0/0:28,0:28:47:0,47,894 0/0:28,0:28:78:0,78,1170 0/0:39,0:39:96:0,96,1440 0/0:42,0:42:99:0,108,1620 0/0:43,0:43:68:0,68,1479 0/0:48,0:48:99:0,120,1800 0/0:44,0:44:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:43,0:43:99:0,114,1569 0/0:66,0:66:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:37,0:37:66:0,66,990 0/0:58,0:58:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:25,0:25:69:0,69,1035 0/0:42,0:42:99:0,108,1620 0/0:41,0:41:99:0,111,1665 0/0:40,0:40:99:0,111,1665 0/0:54,0:54:99:0,120,1800 0/0:38,0:38:96:0,96,1362 0/0:25,0:25:75:0,75,914 0/0:24,0:24:72:0,72,918 0/0:47,0:47:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:39,0:39:99:0,108,1394 0/0:56,0:56:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:42,0:42:99:0,105,1575 0/0:31,0:31:81:0,81,1215 0/0:33,0:33:61:0,61,1225 0/0:28,0:28:81:0,81,1152 0/0:55,0:55:99:0,120,1800 0/0:37,0:37:96:0,96,1424 0/0:52,0:52:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:43,0:43:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/0:42,0:42:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:50,0:50:99:0,117,1755 0/0:20,0:20:60:0,60,731 0/0:29,0:29:66:0,66,990 0/0:68,0:68:99:0,120,1800 0/0:23,0:23:60:0,60,900 0/0:46,0:46:99:0,120,1800 0/0:39,0:39:99:0,111,1665 0/0:58,0:58:99:0,120,1800 0/0:38,0:38:99:0,102,1371 0/0:26,0:26:75:0,75,1099 0/0:27,0:27:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:41,0:41:99:0,120,1800 0/0:31,0:31:93:0,93,1221 0/0:34,0:34:80:0,80,1214 0/0:35,0:35:81:0,81,1215 0/0:22,0:22:60:0,60,802 0/0:31,0:31:72:0,72,1051 0/0:42,0:42:81:0,81,1215 0/0:41,0:41:99:0,111,1665 0/0:57,0:57:99:0,120,1800 0/0:36,0:36:69:0,69,1035 0/0:29,0:29:81:0,81,1178 0/0:39,0:39:99:0,114,1710 0/0:91,0:91:99:0,120,1800 0/0:43,0:43:90:0,90,1350 0/0:25,0:25:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/1:14,22:36:99:746,0,447 0/0:30,0:30:81:0,81,1215 0/0:28,0:28:75:0,75,1125 0/0:32,0:32:63:0,63,945 0/0:29,0:29:84:0,84,1260 0/0:23,0:23:60:0,60,900 0/0:34,0:34:87:0,87,1305 +20 15918214 . A G 1006.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.186;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=37.18;FS=0.0;DP=40299;GQ_MEAN=97.57;VQSLOD=5.37;ClippingRankSum=-0.227;BaseQRankSum=4.78;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=15.98;MQRankSum=0.172;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:44,0:44:93:0,93,1395 0/0:36,0:36:93:0,93,1395 0/0:31,0:31:78:0,78,1204 0/0:46,0:46:99:0,120,1800 0/0:39,0:39:95:0,95,1657 0/0:50,0:50:99:0,120,1800 0/0:51,0:51:99:0,105,1575 0/0:37,0:37:84:0,84,1260 0/0:36,0:36:84:0,84,1260 0/0:32,0:32:66:0,66,1117 0/0:34,0:34:93:0,93,1395 0/0:27,0:27:64:0,64,945 0/0:58,0:58:99:0,120,1800 0/0:41,0:41:90:0,90,1350 0/0:29,0:29:75:0,75,1125 0/0:28,0:28:78:0,78,1170 0/0:39,0:39:96:0,96,1440 0/0:42,0:42:99:0,108,1620 0/0:43,0:43:68:0,68,1479 0/0:48,0:48:99:0,120,1800 0/0:44,0:44:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:43,0:43:99:0,114,1569 0/0:66,0:66:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:37,0:37:66:0,66,990 0/0:58,0:58:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:25,0:25:69:0,69,1035 0/0:42,0:42:99:0,108,1620 0/0:41,0:41:99:0,111,1665 0/0:40,0:40:99:0,111,1665 0/0:54,0:54:99:0,120,1800 0/0:38,0:38:96:0,96,1362 0/0:25,0:25:75:0,75,914 0/0:24,0:24:72:0,72,918 0/0:47,0:47:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:39,0:39:99:0,108,1394 0/0:56,0:56:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:42,0:42:99:0,105,1575 0/0:31,0:31:81:0,81,1215 0/0:33,0:33:61:0,61,1225 0/0:28,0:28:81:0,81,1152 0/0:55,0:55:99:0,120,1800 0/0:37,0:37:96:0,96,1424 0/0:52,0:52:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:43,0:43:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/0:42,0:42:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:50,0:50:99:0,117,1755 0/0:20,0:20:60:0,60,731 0/0:29,0:29:66:0,66,990 0/0:68,0:68:99:0,120,1800 0/0:27,0:27:69:0,69,1035 0/0:46,0:46:99:0,120,1800 0/0:39,0:39:99:0,111,1665 0/0:58,0:58:99:0,120,1800 0/0:38,0:38:99:0,102,1371 0/0:26,0:26:75:0,75,1099 0/1:32,31:63:99:1057,0,965 0/0:38,0:38:90:0,90,1350 0/0:41,0:41:99:0,120,1800 0/0:31,0:31:93:0,93,1221 0/0:34,0:34:80:0,80,1214 0/0:35,0:35:81:0,81,1215 0/0:22,0:22:60:0,60,802 0/0:31,0:31:72:0,72,1051 0/0:42,0:42:81:0,81,1215 0/0:41,0:41:99:0,111,1665 0/0:57,0:57:99:0,120,1800 0/0:36,0:36:69:0,69,1035 0/0:29,0:29:81:0,81,1178 0/0:39,0:39:99:0,114,1710 0/0:91,0:91:99:0,120,1800 0/0:43,0:43:90:0,90,1350 0/0:25,0:25:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:28,0:28:74:0,74,1073 0/0:30,0:30:81:0,81,1215 0/0:28,0:28:75:0,75,1125 0/0:32,0:32:63:0,63,945 0/0:29,0:29:84:0,84,1260 0/0:23,0:23:60:0,60,900 0/0:34,0:34:87:0,87,1305 +20 15948325 . AG A 370.19 VQSRTrancheINDEL99.50to99.90 NEGATIVE_TRAIN_SITE;HWP=1.0;AC=2;culprit=QD;MQ0=0;ReadPosRankSum=2.02;AN=174;InbreedingCoeff=-0.1522;AF=0.007968;GQ_STDDEV=11.02;FS=9.314;DP=20834;GQ_MEAN=8.31;VQSLOD=-1.746;ClippingRankSum=1.32;BaseQRankSum=-2.627;MLEAF=0.013;MLEAC=20;MQ=58.71;QD=1.43;MQRankSum=-0.091;CCC=1506;NCC=117 GT:AD:DP:GQ:PL 0/0:17,0:17:0:0,0,49 0/0:20,0:20:0:0,0,255 0/0:17,0:17:0:0,0,94 0/1:25,7:32:27:27,0,736 0/0:22,0:22:0:0,0,261 0/0:24,0:24:0:0,0,354 0/0:35,0:35:0:0,0,871 0/0:21,0:21:9:0,9,135 0/0:26,0:26:0:0,0,268 0/0:23,0:23:0:0,0,543 0/0:30,0:30:9:0,9,872 0/0:16,0:16:0:0,0,183 0/0:34,0:34:0:0,0,1004 0/0:24,0:24:0:0,0,308 0/0:26,0:26:15:0,15,225 0/0:32,0:32:12:0,12,904 0/0:24,0:24:0:0,0,394 0/0:27,0:27:0:0,0,429 ./.:25,0:25:.:. 0/0:33,0:33:12:0,12,180 0/0:23,0:23:0:0,0,315 0/0:23,0:23:0:0,0,158 0/0:24,0:24:0:0,0,154 0/0:30,0:30:6:0,6,90 ./.:15,0:15:.:. 0/0:47,0:47:30:0,30,450 0/0:24,0:24:6:0,6,90 0/0:34,0:34:9:0,9,135 0/0:22,0:22:9:0,9,135 0/0:22,0:22:15:0,15,225 0/0:28,0:28:0:0,0,634 0/0:18,0:18:6:0,6,90 0/0:48,0:48:21:0,21,315 0/0:76,0:76:21:0,21,315 0/0:35,0:35:6:0,6,90 0/0:11,0:11:0:0,0,45 0/0:17,0:17:12:0,12,180 0/0:17,0:17:0:0,0,14 ./.:30,0:30:.:. 0/0:39,0:39:6:0,6,90 0/0:19,0:19:0:0,0,45 0/1:18,5:23:25:25,0,526 0/0:27,0:27:9:0,9,135 0/0:22,0:22:6:0,6,90 0/0:32,0:32:15:0,15,225 ./.:0,0:.:.:. 0/0:33,0:33:6:0,6,135 0/0:35,0:35:0:0,0,943 0/0:23,0:23:0:0,0,597 0/0:32,0:32:0:0,0,900 0/0:27,0:27:9:0,9,135 0/0:35,0:35:30:0,30,450 0/0:23,0:23:6:0,6,90 0/0:30,0:30:18:0,18,270 0/0:46,0:46:0:0,0,695 ./.:31,0:31:.:. 0/0:33,0:33:0:0,0,635 0/0:37,0:37:0:0,0,45 0/0:44,0:44:9:0,9,135 0/0:36,0:36:21:0,21,315 0/0:37,0:37:6:0,6,90 0/0:27,0:27:12:0,12,180 0/0:55,0:55:9:0,9,135 0/0:30,0:30:12:0,12,180 0/0:30,0:30:9:0,9,135 0/0:17,0:17:6:0,6,472 0/0:14,0:14:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:36,0:36:12:0,12,180 0/0:21,0:21:0:0,0,423 0/0:42,0:42:27:0,27,405 0/0:24,0:24:6:0,6,90 0/0:25,4:29:55:0,55,693 ./.:21,0:21:.:. 0/0:39,0:39:6:0,6,90 0/0:18,0:18:6:0,6,90 0/0:27,0:27:12:0,12,180 ./.:20,0:20:.:. 0/0:29,0:29:12:0,12,180 0/0:27,0:27:6:0,6,90 0/0:18,0:18:6:0,6,90 0/0:28,0:28:6:0,6,90 0/0:21,0:21:6:0,6,90 0/0:35,0:35:15:0,15,225 0/0:20,0:20:0:0,0,45 ./.:0,0:.:.:. 0/0:29,0:29:18:0,18,270 ./.:9,0:9:.:. 0/0:32,0:32:0:0,0,774 0/0:42,0:42:18:0,18,270 0/0:6,0:6:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:21,0:21:9:0,9,135 0/0:22,0:22:0:0,0,251 ./.:0,0:.:.:. ./.:7,0:7:.:. 0/0:24,0:24:9:0,9,135 ./.:16,0:16:.:. 0/0:20,0:20:0:0,0,532 ./.:23,0:23:.:. +20 15948326 . G A 20813.60 VQSRTrancheINDEL97.00to99.00 HWP=0.1922;AC=4;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.731;AN=182;InbreedingCoeff=0.5933;AF=0.032;GQ_STDDEV=59.94;FS=2.695;DP=21206;GQ_MEAN=23.71;VQSLOD=0.243;ClippingRankSum=-0.968;BaseQRankSum=-1.531;MLEAF=0.032;MLEAC=49;MQ=57.2;QD=6.02;MQRankSum=-0.34;CCC=1522;NCC=109 GT:AD:DP:GQ:PL 0/0:17,0:17:0:0,0,49 0/0:20,0:20:0:0,0,255 0/0:17,0:17:0:0,0,94 0/0:32,1:33:90:0,90,925 0/0:22,0:22:0:0,0,261 0/0:24,0:24:0:0,0,354 0/0:1,0:5:3:0,3,7 0/0:24,0:24:0:0,0,255 0/0:26,0:26:0:0,0,268 0/0:3,0:7:9:0,9,75 0/1:18,13:31:99:191,0,477 0/0:16,0:16:0:0,0,183 0/1:0,10:13:78:78,0,779 0/0:24,0:24:0:0,0,308 0/0:26,0:26:0:0,0,292 0/0:34,0:34:0:0,0,143 0/0:5,0:20:0:0,0,127 0/0:27,0:27:0:0,0,429 0/0:6,0:13:18:0,18,172 0/0:32,0:32:0:0,0,739 0/0:23,0:23:0:0,0,315 0/0:23,0:23:0:0,0,158 0/0:24,0:24:0:0,0,154 0/0:30,0:30:6:0,6,90 ./.:15,0:15:.:. 0/0:5,0:20:15:0,15,102 0/0:22,0:22:0:0,0,306 0/0:33,0:33:0:0,0,713 0/0:20,0:20:0:0,0,457 0/0:20,0:20:0:0,0,355 0/0:6,0:10:18:0,18,263 0/0:16,0:16:0:0,0,449 0/0:50,0:50:0:0,0,997 0/0:76,0:76:0:0,0,1815 0/0:34,0:34:0:0,0,676 0/0:11,0:11:0:0,0,45 0/0:14,0:14:0:0,0,312 0/0:17,0:17:0:0,0,14 0/0:13,0:18:39:0,39,283 0/0:36,0:36:0:0,0,699 0/0:19,0:19:0:0,0,45 ./.:0,0:.:.:. 0/0:26,0:26:0:0,0,451 0/0:21,0:21:0:0,0,318 0/0:3,0:8:11:0,11,45 0/0:5,4:14:51:0,51,1111 0/0:5,0:12:15:0,15,61 0/0:18,0:27:53:0,53,509 0/0:23,0:23:0:0,0,597 0/0:6,0:13:18:0,18,81 0/0:28,0:28:0:0,0,580 0/0:11,0:17:33:0,33,317 0/0:23,0:23:0:0,0,212 0/0:30,0:30:0:0,0,552 0/0:46,0:46:0:0,0,695 ./.:31,0:31:.:. 0/0:33,0:33:0:0,0,635 0/0:37,0:37:0:0,0,45 0/0:35,0:35:0:0,0,727 0/0:42,0:42:0:0,0,523 0/0:7,0:19:0:0,0,103 0/0:28,0:28:0:0,0,473 0/0:57,0:57:0:0,0,605 0/0:31,0:31:0:0,0,643 0/0:25,0:29:73:0,73,856 0/0:16,0:16:0:0,0,28 0/0:14,0:14:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:15,0:22:46:0,46,365 0/0:21,0:21:0:0,0,423 0/0:40,0:40:0:0,0,563 0/0:25,0:25:0:0,0,300 0/0:4,2:13:62:0,62,751 ./.:21,0:21:.:. 0/0:9,0:15:27:0,27,309 0/0:17,0:17:0:0,0,525 0/0:16,0:20:46:0,46,609 ./.:20,0:20:.:. 0/0:22,0:22:0:0,0,384 0/0:3,0:15:8:0,8,38 0/0:19,0:19:0:0,0,286 0/0:28,0:28:0:0,0,688 0/0:17,0:17:0:0,0,441 0/0:30,0:30:0:0,0,701 0/0:20,0:20:0:0,0,45 0/0:3,1:20:99:0,117,1630 0/1:17,8:25:95:95,0,530 ./.:9,0:9:.:. 0/0:3,0:20:0:0,10,0 0/0:24,0:30:71:0,71,749 0/0:6,0:6:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:25,0:25:0:0,0,240 0/0:22,0:22:0:0,0,251 0/1:2,4:9:24:24,0,443 ./.:7,0:7:.:. 0/0:21,0:21:0:0,0,488 ./.:16,0:16:.:. 0/0:20,0:20:0:0,0,532 ./.:23,0:23:.:. +20 15948326 . G GA 20813.60 VQSRTrancheINDEL97.00to99.00 HWP=0.1922;AC=7;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.731;AN=182;InbreedingCoeff=0.5933;AF=0.025;GQ_STDDEV=59.94;FS=2.695;DP=21206;GQ_MEAN=23.71;VQSLOD=0.243;ClippingRankSum=-0.968;BaseQRankSum=-1.531;MLEAF=0.021;MLEAC=32;MQ=57.2;QD=6.02;MQRankSum=-0.34;CCC=1522;NCC=109 GT:AD:DP:GQ:PL 0/0:17,0:17:0:0,0,49 0/0:20,0:20:0:0,0,255 0/0:17,0:17:0:0,0,94 0/0:32,0:33:97:0,97,935 0/0:22,0:22:0:0,0,261 0/0:24,0:24:0:0,0,354 1/1:1,4:5:8:52,8,0 0/0:24,0:24:0:0,0,255 0/0:26,0:26:0:0,0,268 0/0:3,0:7:9:0,9,75 0/0:18,0:31:51:0,51,574 0/0:16,0:16:0:0,0,183 0/0:0,0:13:6:0,6,13 0/0:24,0:24:0:0,0,308 0/0:26,0:26:0:0,0,292 0/0:34,0:34:0:0,0,143 0/0:5,0:20:0:0,0,127 0/0:27,0:27:0:0,0,429 0/0:6,0:13:18:0,18,172 0/0:32,0:32:0:0,0,739 0/0:23,0:23:0:0,0,315 0/0:23,0:23:0:0,0,158 0/0:24,0:24:0:0,0,154 0/0:30,0:30:6:0,6,90 ./.:15,0:15:.:. 0/1:5,7:20:79:79,0,129 0/0:22,0:22:0:0,0,306 0/0:33,0:33:0:0,0,713 0/0:20,0:20:0:0,0,457 0/0:20,0:20:0:0,0,355 0/0:6,0:10:18:0,18,263 0/0:16,0:16:0:0,0,449 0/0:50,0:50:0:0,0,997 0/0:76,0:76:0:0,0,1815 0/0:34,0:34:0:0,0,676 0/0:11,0:11:0:0,0,45 0/0:14,0:14:0:0,0,312 0/0:17,0:17:0:0,0,14 0/0:13,0:18:39:0,39,283 0/0:36,0:36:0:0,0,699 0/0:19,0:19:0:0,0,45 ./.:0,0:.:.:. 0/0:26,0:26:0:0,0,451 0/0:21,0:21:0:0,0,318 0/1:3,5:8:20:74,0,20 0/0:5,0:14:19:0,19,77 0/1:5,7:12:25:103,0,25 0/0:18,0:27:53:0,53,509 0/0:23,0:23:0:0,0,597 0/1:6,7:13:38:109,0,38 0/0:28,0:28:0:0,0,580 0/0:11,0:17:33:0,33,317 0/0:23,0:23:0:0,0,212 0/0:30,0:30:0:0,0,552 0/0:46,0:46:0:0,0,695 ./.:31,0:31:.:. 0/0:33,0:33:0:0,0,635 0/0:37,0:37:0:0,0,45 0/0:35,0:35:0:0,0,727 0/0:42,0:42:0:0,0,523 0/0:7,0:19:0:0,0,103 0/0:28,0:28:0:0,0,473 0/0:57,0:57:0:0,0,605 0/0:31,0:31:0:0,0,643 0/0:25,0:29:73:0,73,856 0/0:16,0:16:0:0,0,28 0/0:14,0:14:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:15,0:22:46:0,46,365 0/0:21,0:21:0:0,0,423 0/0:40,0:40:0:0,0,563 0/0:25,0:25:0:0,0,300 0/0:4,0:13:13:0,13,41 ./.:21,0:21:.:. 0/0:9,0:15:27:0,27,309 0/0:17,0:17:0:0,0,525 0/0:16,0:20:46:0,46,609 ./.:20,0:20:.:. 0/0:22,0:22:0:0,0,384 0/1:3,4:15:37:37,0,76 0/0:19,0:19:0:0,0,286 0/0:28,0:28:0:0,0,688 0/0:17,0:17:0:0,0,441 0/0:30,0:30:0:0,0,701 0/0:20,0:20:0:0,0,45 0/0:3,0:20:0:0,0,14 0/0:17,0:25:51:0,51,605 ./.:9,0:9:.:. 0/0:3,0:20:0:0,10,0 0/0:24,0:30:71:0,71,749 0/0:6,0:6:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:25,0:25:0:0,0,240 0/0:22,0:22:0:0,0,251 0/0:2,0:9:10:0,10,53 ./.:7,0:7:.:. 0/0:21,0:21:0:0,0,488 ./.:16,0:16:.:. 0/0:20,0:20:0:0,0,532 ./.:23,0:23:.:. +20 15948326 . GAA G 20813.60 VQSRTrancheINDEL97.00to99.00 HWP=0.1922;AC=4;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.731;AN=182;InbreedingCoeff=0.5933;AF=0.015;GQ_STDDEV=59.94;FS=2.695;DP=21206;GQ_MEAN=23.71;VQSLOD=0.243;ClippingRankSum=-0.968;BaseQRankSum=-1.531;MLEAF=0.016;MLEAC=25;MQ=57.2;QD=6.02;MQRankSum=-0.34;CCC=1522;NCC=109 GT:AD:DP:GQ:PL 0/0:17,0:17:0:0,0,49 0/0:20,0:20:0:0,0,255 0/0:17,0:17:0:0,0,94 0/0:32,0:33:97:0,97,935 0/0:22,0:22:0:0,0,261 0/0:24,0:24:0:0,0,354 0/0:1,0:5:3:0,3,7 0/0:24,0:24:0:0,0,255 0/0:26,0:26:0:0,0,268 0/1:3,4:7:51:95,0,51 0/0:18,0:31:51:0,51,574 0/0:16,0:16:0:0,0,183 0/0:0,0:13:6:0,6,13 0/0:24,0:24:0:0,0,308 0/0:26,0:26:0:0,0,292 0/0:34,0:34:0:0,0,143 0/0:5,0:20:0:0,0,127 0/0:27,0:27:0:0,0,429 0/0:6,0:13:18:0,18,172 0/0:32,0:32:0:0,0,739 0/0:23,0:23:0:0,0,315 0/0:23,0:23:0:0,0,158 0/0:24,0:24:0:0,0,154 0/0:30,0:30:6:0,6,90 ./.:15,0:15:.:. 0/1:5,8:20:99:154,0,319 0/0:22,0:22:0:0,0,306 0/0:33,0:33:0:0,0,713 0/0:20,0:20:0:0,0,457 0/0:20,0:20:0:0,0,355 0/0:6,0:10:18:0,18,263 0/0:16,0:16:0:0,0,449 0/0:50,0:50:0:0,0,997 0/0:76,0:76:0:0,0,1815 0/0:34,0:34:0:0,0,676 0/0:11,0:11:0:0,0,45 0/0:14,0:14:0:0,0,312 0/0:17,0:17:0:0,0,14 0/1:13,5:18:87:87,0,226 0/0:36,0:36:0:0,0,699 0/0:19,0:19:0:0,0,45 ./.:0,0:.:.:. 0/0:26,0:26:0:0,0,451 0/0:21,0:21:0:0,0,318 0/0:3,0:8:11:0,11,45 0/0:5,0:14:19:0,19,77 0/0:5,0:12:15:0,15,61 0/0:18,0:27:53:0,53,509 0/0:23,0:23:0:0,0,597 0/0:6,0:13:18:0,18,81 0/0:28,0:28:0:0,0,580 0/0:11,0:17:33:0,33,317 0/0:23,0:23:0:0,0,212 0/0:30,0:30:0:0,0,552 0/0:46,0:46:0:0,0,695 ./.:31,0:31:.:. 0/0:33,0:33:0:0,0,635 0/0:37,0:37:0:0,0,45 0/0:35,0:35:0:0,0,727 0/0:42,0:42:0:0,0,523 0/0:7,5:19:0:0,0,100 0/0:28,0:28:0:0,0,473 0/0:57,0:57:0:0,0,605 0/0:31,0:31:0:0,0,643 0/0:25,0:29:73:0,73,856 0/0:16,0:16:0:0,0,28 0/0:14,0:14:0:0,0,45 0/0:9,0:9:0:0,0,45 0/1:15,7:22:99:125,0,293 0/0:21,0:21:0:0,0,423 0/0:40,0:40:0:0,0,563 0/0:25,0:25:0:0,0,300 0/0:4,0:13:13:0,13,41 ./.:21,0:21:.:. 0/0:9,0:15:27:0,27,309 0/0:17,0:17:0:0,0,525 0/0:16,0:20:46:0,46,609 ./.:20,0:20:.:. 0/0:22,0:22:0:0,0,384 0/0:3,0:15:8:0,8,38 0/0:19,0:19:0:0,0,286 0/0:28,0:28:0:0,0,688 0/0:17,0:17:0:0,0,441 0/0:30,0:30:0:0,0,701 0/0:20,0:20:0:0,0,45 0/0:3,0:20:0:0,0,14 0/0:17,0:25:51:0,51,605 ./.:9,0:9:.:. 0/0:3,0:20:0:0,10,0 0/0:24,0:30:71:0,71,749 0/0:6,0:6:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:25,0:25:0:0,0,240 0/0:22,0:22:0:0,0,251 0/0:2,0:9:10:0,10,53 ./.:7,0:7:.:. 0/0:21,0:21:0:0,0,488 ./.:16,0:16:.:. 0/0:20,0:20:0:0,0,532 ./.:23,0:23:.:. +20 15948326 . GAAA G 20813.60 VQSRTrancheINDEL97.00to99.00 HWP=0.1922;AC=8;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.731;AN=182;InbreedingCoeff=0.5933;AF=0.025;GQ_STDDEV=59.94;FS=2.695;DP=21206;GQ_MEAN=23.71;VQSLOD=0.243;ClippingRankSum=-0.968;BaseQRankSum=-1.531;MLEAF=0.027;MLEAC=41;MQ=57.2;QD=6.02;MQRankSum=-0.34;CCC=1522;NCC=109 GT:AD:DP:GQ:PL 0/0:17,0:17:0:0,0,49 0/0:20,0:20:0:0,0,255 0/0:17,0:17:0:0,0,94 0/0:32,0:33:97:0,97,935 0/0:22,0:22:0:0,0,261 0/0:24,0:24:0:0,0,354 0/0:1,0:5:3:0,3,7 0/0:24,0:24:0:0,0,255 0/0:26,0:26:0:0,0,268 0/0:3,0:7:9:0,9,75 0/0:18,0:31:51:0,51,574 0/0:16,0:16:0:0,0,183 0/0:0,0:13:6:0,6,13 0/0:24,0:24:0:0,0,308 0/0:26,0:26:0:0,0,292 0/0:34,0:34:0:0,0,143 0/0:5,0:20:0:0,0,127 0/0:27,0:27:0:0,0,429 0/1:6,7:13:99:210,0,131 0/0:32,0:32:0:0,0,739 0/0:23,0:23:0:0,0,315 0/0:23,0:23:0:0,0,158 0/0:24,0:24:0:0,0,154 0/0:30,0:30:6:0,6,90 ./.:15,0:15:.:. 0/0:5,0:20:15:0,15,102 0/0:22,0:22:0:0,0,306 0/0:33,0:33:0:0,0,713 0/0:20,0:20:0:0,0,457 0/0:20,0:20:0:0,0,355 0/0:6,0:10:18:0,18,263 0/0:16,0:16:0:0,0,449 0/0:50,0:50:0:0,0,997 0/0:76,0:76:0:0,0,1815 0/0:34,0:34:0:0,0,676 0/0:11,0:11:0:0,0,45 0/0:14,0:14:0:0,0,312 0/0:17,0:17:0:0,0,14 0/0:13,0:18:39:0,39,283 0/0:36,0:36:0:0,0,699 0/0:19,0:19:0:0,0,45 ./.:0,0:.:.:. 0/0:26,0:26:0:0,0,451 0/0:21,0:21:0:0,0,318 0/0:3,0:8:11:0,11,45 0/1:5,5:14:44:44,0,549 0/0:5,0:12:15:0,15,61 0/1:18,9:27:99:188,0,424 0/0:23,0:23:0:0,0,597 0/0:6,0:13:18:0,18,81 0/0:28,0:28:0:0,0,580 0/1:11,6:17:99:169,0,259 0/0:23,0:23:0:0,0,212 0/0:30,0:30:0:0,0,552 0/0:46,0:46:0:0,0,695 ./.:31,0:31:.:. 0/0:33,0:33:0:0,0,635 0/0:37,0:37:0:0,0,45 0/0:35,0:35:0:0,0,727 0/0:42,0:42:0:0,0,523 0/1:7,7:19:99:251,0,224 0/0:28,0:28:0:0,0,473 0/0:57,0:57:0:0,0,605 0/0:31,0:31:0:0,0,643 0/0:25,0:29:73:0,73,856 0/0:16,0:16:0:0,0,28 0/0:14,0:14:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:15,0:22:46:0,46,365 0/0:21,0:21:0:0,0,423 0/0:40,0:40:0:0,0,563 0/0:25,0:25:0:0,0,300 0/0:4,0:13:13:0,13,41 ./.:21,0:21:.:. 0/0:9,0:15:27:0,27,309 0/0:17,0:17:0:0,0,525 0/0:16,0:20:46:0,46,609 ./.:20,0:20:.:. 0/0:22,0:22:0:0,0,384 0/0:3,0:15:8:0,8,38 0/0:19,0:19:0:0,0,286 0/0:28,0:28:0:0,0,688 0/0:17,0:17:0:0,0,441 0/0:30,0:30:0:0,0,701 0/0:20,0:20:0:0,0,45 0/1:3,9:20:82:82,0,195 0/0:17,0:25:51:0,51,605 ./.:9,0:9:.:. 0/1:3,8:20:0:403,0,0 0/1:24,6:30:97:97,0,650 0/0:6,0:6:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:25,0:25:0:0,0,240 0/0:22,0:22:0:0,0,251 0/0:2,3:9:0:0,0,228 ./.:7,0:7:.:. 0/0:21,0:21:0:0,0,488 ./.:16,0:16:.:. 0/0:20,0:20:0:0,0,532 ./.:23,0:23:.:. +20 15948326 . GAAAA G 20813.60 VQSRTrancheINDEL97.00to99.00 HWP=0.1922;AC=5;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.731;AN=182;InbreedingCoeff=0.5933;AF=0.019;GQ_STDDEV=59.94;FS=2.695;DP=21206;GQ_MEAN=23.71;VQSLOD=0.243;ClippingRankSum=-0.968;BaseQRankSum=-1.531;MLEAF=0.019;MLEAC=29;MQ=57.2;QD=6.02;MQRankSum=-0.34;CCC=1522;NCC=109 GT:AD:DP:GQ:PL 0/0:17,0:17:0:0,0,49 0/0:20,0:20:0:0,0,255 0/0:17,0:17:0:0,0,94 0/0:32,0:33:97:0,97,935 0/0:22,0:22:0:0,0,261 0/0:24,0:24:0:0,0,354 0/0:1,0:5:3:0,3,7 0/0:24,0:24:0:0,0,255 0/0:26,0:26:0:0,0,268 0/0:3,0:7:9:0,9,75 0/0:18,0:31:51:0,51,574 0/0:16,0:16:0:0,0,183 0/1:0,3:13:0:0,0,870 0/0:24,0:24:0:0,0,308 0/0:26,0:26:0:0,0,292 0/0:34,0:34:0:0,0,143 0/0:5,0:20:0:0,0,127 0/0:27,0:27:0:0,0,429 0/0:6,0:13:18:0,18,172 0/0:32,0:32:0:0,0,739 0/0:23,0:23:0:0,0,315 0/0:23,0:23:0:0,0,158 0/0:24,0:24:0:0,0,154 0/0:30,0:30:6:0,6,90 ./.:15,0:15:.:. 0/0:5,0:20:15:0,15,102 0/0:22,0:22:0:0,0,306 0/0:33,0:33:0:0,0,713 0/0:20,0:20:0:0,0,457 0/0:20,0:20:0:0,0,355 0/0:6,0:10:18:0,18,263 0/0:16,0:16:0:0,0,449 0/0:50,0:50:0:0,0,997 0/0:76,0:76:0:0,0,1815 0/0:34,0:34:0:0,0,676 0/0:11,0:11:0:0,0,45 0/0:14,0:14:0:0,0,312 0/0:17,0:17:0:0,0,14 0/0:13,0:18:39:0,39,283 0/0:36,0:36:0:0,0,699 0/0:19,0:19:0:0,0,45 ./.:0,0:.:.:. 0/0:26,0:26:0:0,0,451 0/0:21,0:21:0:0,0,318 0/0:3,0:8:11:0,11,45 0/0:5,0:14:19:0,19,77 0/0:5,0:12:15:0,15,61 0/0:18,0:27:53:0,53,509 0/0:23,0:23:0:0,0,597 0/0:6,0:13:18:0,18,81 0/0:28,0:28:0:0,0,580 0/0:11,0:17:33:0,33,317 0/0:23,0:23:0:0,0,212 0/0:30,0:30:0:0,0,552 0/0:46,0:46:0:0,0,695 ./.:31,0:31:.:. 0/0:33,0:33:0:0,0,635 0/0:37,0:37:0:0,0,45 0/0:35,0:35:0:0,0,727 0/0:42,0:42:0:0,0,523 0/0:7,0:19:0:0,0,103 0/0:28,0:28:0:0,0,473 0/0:57,0:57:0:0,0,605 0/0:31,0:31:0:0,0,643 0/1:25,4:29:76:76,0,765 0/0:16,0:16:0:0,0,28 0/0:14,0:14:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:15,0:22:46:0,46,365 0/0:21,0:21:0:0,0,423 0/0:40,0:40:0:0,0,563 0/0:25,0:25:0:0,0,300 0/0:4,0:13:13:0,13,41 ./.:21,0:21:.:. 0/1:9,6:15:99:160,0,255 0/0:17,0:17:0:0,0,525 0/1:16,4:20:99:105,0,541 ./.:20,0:20:.:. 0/0:22,0:22:0:0,0,384 0/0:3,0:15:8:0,8,38 0/0:19,0:19:0:0,0,286 0/0:28,0:28:0:0,0,688 0/0:17,0:17:0:0,0,441 0/0:30,0:30:0:0,0,701 0/0:20,0:20:0:0,0,45 0/0:3,7:20:0:0,0,345 0/0:17,0:25:51:0,51,605 ./.:9,0:9:.:. 0/1:3,9:20:45:390,0,45 0/0:24,0:30:71:0,71,749 0/0:6,0:6:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:25,0:25:0:0,0,240 0/0:22,0:22:0:0,0,251 0/0:2,0:9:10:0,10,53 ./.:7,0:7:.:. 0/0:21,0:21:0:0,0,488 ./.:16,0:16:.:. 0/0:20,0:20:0:0,0,532 ./.:23,0:23:.:. +20 15948326 . GAAAAAA G 20813.60 VQSRTrancheINDEL97.00to99.00 HWP=0.1922;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.731;AN=182;InbreedingCoeff=0.5933;AF=0.017;GQ_STDDEV=59.94;FS=2.695;DP=21206;GQ_MEAN=23.71;VQSLOD=0.243;ClippingRankSum=-0.968;BaseQRankSum=-1.531;MLEAF=0.018;MLEAC=27;MQ=57.2;QD=6.02;MQRankSum=-0.34;CCC=1522;NCC=109 GT:AD:DP:GQ:PL 0/0:17,0:17:0:0,0,49 0/0:20,0:20:0:0,0,255 0/0:17,0:17:0:0,0,94 0/0:32,0:33:97:0,97,935 0/0:22,0:22:0:0,0,261 0/0:24,0:24:0:0,0,354 0/0:1,0:5:3:0,3,7 0/0:24,0:24:0:0,0,255 0/0:26,0:26:0:0,0,268 0/0:3,0:7:9:0,9,75 0/0:18,0:31:51:0,51,574 0/0:16,0:16:0:0,0,183 0/0:0,0:13:6:0,6,13 0/0:24,0:24:0:0,0,308 0/0:26,0:26:0:0,0,292 0/0:34,0:34:0:0,0,143 0/1:5,7:20:99:420,0,171 0/0:27,0:27:0:0,0,429 0/0:6,0:13:18:0,18,172 0/0:32,0:32:0:0,0,739 0/0:23,0:23:0:0,0,315 0/0:23,0:23:0:0,0,158 0/0:24,0:24:0:0,0,154 0/0:30,0:30:6:0,6,90 ./.:15,0:15:.:. 0/0:5,0:20:15:0,15,102 0/0:22,0:22:0:0,0,306 0/0:33,0:33:0:0,0,713 0/0:20,0:20:0:0,0,457 0/0:20,0:20:0:0,0,355 0/0:6,0:10:18:0,18,263 0/0:16,0:16:0:0,0,449 0/0:50,0:50:0:0,0,997 0/0:76,0:76:0:0,0,1815 0/0:34,0:34:0:0,0,676 0/0:11,0:11:0:0,0,45 0/0:14,0:14:0:0,0,312 0/0:17,0:17:0:0,0,14 0/0:13,0:18:39:0,39,283 0/0:36,0:36:0:0,0,699 0/0:19,0:19:0:0,0,45 ./.:0,0:.:.:. 0/0:26,0:26:0:0,0,451 0/0:21,0:21:0:0,0,318 0/0:3,0:8:11:0,11,45 0/0:5,0:14:19:0,19,77 0/0:5,0:12:15:0,15,61 0/0:18,0:27:53:0,53,509 0/0:23,0:23:0:0,0,597 0/0:6,0:13:18:0,18,81 0/0:28,0:28:0:0,0,580 0/0:11,0:17:33:0,33,317 0/0:23,0:23:0:0,0,212 0/0:30,0:30:0:0,0,552 0/0:46,0:46:0:0,0,695 ./.:31,0:31:.:. 0/0:33,0:33:0:0,0,635 0/0:37,0:37:0:0,0,45 0/0:35,0:35:0:0,0,727 0/0:42,0:42:0:0,0,523 0/0:7,0:19:0:0,0,103 0/0:28,0:28:0:0,0,473 0/0:57,0:57:0:0,0,605 0/0:31,0:31:0:0,0,643 0/0:25,0:29:73:0,73,856 0/0:16,0:16:0:0,0,28 0/0:14,0:14:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:15,0:22:46:0,46,365 0/0:21,0:21:0:0,0,423 0/0:40,0:40:0:0,0,563 0/0:25,0:25:0:0,0,300 0/0:4,0:13:13:0,13,41 ./.:21,0:21:.:. 0/0:9,0:15:27:0,27,309 0/0:17,0:17:0:0,0,525 0/0:16,0:20:46:0,46,609 ./.:20,0:20:.:. 0/0:22,0:22:0:0,0,384 0/0:3,0:15:8:0,8,38 0/0:19,0:19:0:0,0,286 0/0:28,0:28:0:0,0,688 0/0:17,0:17:0:0,0,441 0/0:30,0:30:0:0,0,701 0/0:20,0:20:0:0,0,45 0/0:3,0:20:0:0,0,14 0/0:17,0:25:51:0,51,605 ./.:9,0:9:.:. 0/0:3,0:20:0:0,10,0 0/0:24,0:30:71:0,71,749 0/0:6,0:6:0:0,0,45 0/0:9,0:9:0:0,0,45 0/0:25,0:25:0:0,0,240 0/0:22,0:22:0:0,0,251 0/0:2,0:9:10:0,10,53 ./.:7,0:7:.:. 0/0:21,0:21:0:0,0,488 ./.:16,0:16:.:. 0/0:20,0:20:0:0,0,532 ./.:23,0:23:.:. +20 15967327 rs34675181 A G 149940.00 PASS HWP=3.0E-4;AC=91;culprit=MQ;MQ0=0;ReadPosRankSum=0.258;AN=200;InbreedingCoeff=0.1033;AF=0.329;GQ_STDDEV=105.68;FS=0.0;DP=13851;GQ_MEAN=99.72;POSITIVE_TRAIN_SITE;VQSLOD=6.47;ClippingRankSum=0.041;BaseQRankSum=-1.91;MLEAF=0.335;MLEAC=582;MQ=60.0;QD=18.92;DB;MQRankSum=0.156;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:17,0:17:31:0,31,675 0/0:18,0:18:18:0,18,609 0/1:5,3:8:80:80,0,174 0/0:15,0:15:38:0,38,513 1/1:0,17:17:51:582,51,0 0/1:7,14:21:99:427,0,197 0/0:16,0:16:30:0,30,565 0/0:18,0:18:25:0,25,580 0/1:8,10:18:99:303,0,262 0/0:10,0:10:24:0,24,360 1/1:0,17:17:51:596,51,0 0/1:3,11:14:66:316,0,66 1/1:1,19:20:18:633,18,0 0/0:15,0:15:42:0,42,630 0/0:13,0:13:39:0,39,400 1/1:0,24:24:72:835,72,0 0/0:17,0:17:39:0,39,585 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:12,11:23:99:318,0,362 0/0:21,0:21:60:0,60,900 0/0:18,0:18:45:0,45,675 1/1:0,26:26:78:836,78,0 0/0:14,0:14:39:0,39,585 0/1:7,10:17:99:293,0,234 0/0:15,0:15:42:0,42,630 0/0:14,0:14:36:0,36,521 0/1:9,7:16:99:182,0,290 1/1:0,16:16:48:558,48,0 0/0:27,0:27:60:0,60,900 0/1:13,9:22:99:244,0,371 0/1:4,10:14:99:330,0,120 0/0:22,0:22:62:0,62,945 0/0:28,0:28:64:0,64,1035 1/1:0,30:30:90:1063,90,0 0/0:7,0:7:21:0,21,262 0/0:12,0:12:36:0,36,423 0/1:14,15:29:99:415,0,412 0/1:9,5:14:99:129,0,290 0/0:22,0:22:60:0,60,802 0/1:11,6:17:99:150,0,377 0/0:7,0:7:18:0,18,270 0/0:13,0:13:30:0,30,450 0/1:8,8:16:99:219,0,253 0/1:4,13:17:99:372,0,102 0/0:10,0:10:27:0,27,405 0/1:7,8:15:99:226,0,213 0/1:8,9:17:99:246,0,242 0/1:15,12:27:99:346,0,498 1/1:0,26:26:78:900,78,0 0/1:6,9:15:99:255,0,178 0/1:7,6:13:99:162,0,217 0/1:5,6:11:99:153,0,125 1/1:0,18:18:54:624,54,0 0/1:13,14:27:99:392,0,409 0/1:10,10:20:99:236,0,296 0/1:8,14:22:99:391,0,243 0/1:6,11:17:99:323,0,173 1/1:0,10:10:30:326,30,0 0/1:13,12:25:99:358,0,419 0/0:14,0:14:39:0,39,515 1/1:0,15:15:45:499,45,0 0/1:9,9:18:99:270,0,291 0/1:10,9:19:99:227,0,312 0/0:17,0:17:37:0,37,630 0/1:10,9:19:99:266,0,316 1/1:0,8:8:24:287,24,0 0/0:9,0:9:21:0,21,315 1/1:0,25:25:75:911,75,0 0/0:8,0:8:24:0,24,295 1/1:0,14:14:42:489,42,0 1/1:0,19:19:57:691,57,0 1/1:0,17:17:51:576,51,0 0/0:10,0:10:27:0,27,398 0/1:7,10:17:99:307,0,219 0/1:5,7:12:99:216,0,144 1/1:0,14:14:42:488,42,0 0/1:8,6:14:99:177,0,266 0/1:3,12:15:70:393,0,70 0/1:13,8:21:99:229,0,435 1/1:0,6:6:18:225,18,0 0/1:3,8:11:85:258,0,85 0/0:2,0:2:6:0,6,74 1/1:0,23:23:69:794,69,0 0/1:6,6:12:99:181,0,195 1/1:0,22:22:66:797,66,0 0/1:5,4:9:99:114,0,164 0/1:8,5:13:99:141,0,264 0/0:9,0:9:24:0,24,360 1/1:0,24:24:72:857,72,0 0/0:18,0:18:48:0,48,720 0/1:8,3:11:67:67,0,256 1/1:0,14:14:42:520,42,0 0/1:2,5:7:57:158,0,57 0/1:2,14:16:30:434,0,30 0/1:4,9:13:99:239,0,119 0/1:7,5:12:99:144,0,236 1/1:0,16:16:48:555,48,0 1/1:0,9:9:27:329,27,0 0/1:6,8:14:99:246,0,183 +20 15967390 rs41275442 C T 51516.80 PASS HWP=0.0601;AC=18;culprit=MQ;MQ0=0;ReadPosRankSum=0.276;AN=200;InbreedingCoeff=0.0732;AF=0.072;GQ_STDDEV=132.08;FS=1.144;DP=20599;GQ_MEAN=99.98;POSITIVE_TRAIN_SITE;VQSLOD=5.26;ClippingRankSum=0.231;BaseQRankSum=-0.737;MLEAF=0.072;MLEAC=126;MQ=60.0;QD=12.18;DB;MQRankSum=0.159;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,735 0/0:22,0:22:60:0,60,863 0/0:20,0:20:60:0,60,744 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,742 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,849 0/0:23,0:23:63:0,63,945 0/1:23,11:34:99:269,0,645 0/0:22,0:22:60:0,60,784 0/0:26,0:26:63:0,63,945 0/0:22,0:22:60:0,60,900 0/1:35,24:59:99:571,0,997 0/1:21,18:39:99:501,0,602 0/0:26,0:26:69:0,69,1035 0/0:25,0:25:60:0,60,879 0/0:27,0:27:66:0,66,990 0/0:26,0:26:63:0,63,945 0/1:31,32:63:99:813,0,921 0/0:20,0:20:60:0,60,675 0/0:20,0:20:60:0,60,719 0/1:21,19:40:99:565,0,565 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,719 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,798 0/0:22,0:22:62:0,62,945 0/0:28,0:28:64:0,64,1035 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,712 0/0:29,0:29:60:0,60,900 0/1:17,18:35:99:522,0,505 0/0:22,0:22:60:0,60,802 0/0:15,0:15:37:0,37,534 0/1:7,10:17:99:323,0,207 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,808 0/1:11,13:24:99:407,0,330 0/0:23,0:23:60:0,60,900 0/1:16,14:30:99:380,0,508 0/0:24,0:24:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:24,0:24:60:0,60,900 0/1:13,13:26:99:389,0,388 0/1:10,16:26:99:477,0,266 0/0:21,0:21:60:0,60,870 0/0:21,0:21:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:30,11:41:99:297,0,951 0/0:21,0:21:60:0,60,761 0/0:25,0:25:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:22,0:22:60:0,60,870 0/0:25,0:25:60:0,60,886 0/1:13,9:22:99:275,0,341 0/0:23,0:23:60:0,60,900 0/1:11,13:24:99:343,0,373 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:20,0:20:60:0,60,716 0/1:13,11:24:99:268,0,419 0/0:20,0:20:60:0,60,679 0/0:21,0:21:60:0,60,896 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:63:0,63,990 0/0:7,0:7:21:0,21,252 0/0:22,0:22:60:0,60,900 1/1:0,9:9:27:291,27,0 0/0:24,0:24:63:0,63,774 0/0:25,0:25:60:0,60,900 0/0:24,0:24:64:0,64,990 0/0:21,0:21:60:0,60,900 0/1:14,23:37:99:528,0,352 0/0:21,0:21:60:0,60,751 0/0:24,0:24:60:0,60,900 0/0:31,0:31:78:0,78,1170 0/0:23,0:23:60:0,60,852 0/0:22,0:22:60:0,60,900 0/0:7,0:7:21:0,21,275 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,722 0/0:11,0:11:33:0,33,402 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,780 0/0:21,0:21:60:0,60,879 +20 15967719 rs62194199 T C 115009.00 PASS HWP=0.0499;AC=13;culprit=FS;MQ0=0;ReadPosRankSum=0.925;AN=200;InbreedingCoeff=0.0916;AF=0.037;GQ_STDDEV=377.95;FS=0.0;DP=33728;GQ_MEAN=167.86;POSITIVE_TRAIN_SITE;VQSLOD=6.86;ClippingRankSum=-0.595;BaseQRankSum=3.76;MLEAF=0.037;MLEAC=64;MQ=59.66;QD=15.46;DB;MQRankSum=0.193;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:61:0,61,945 0/0:24,0:24:60:0,60,900 0/1:46,32:78:99:861,0,1311 0/0:26,0:26:63:0,63,945 0/0:38,0:38:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:57,0:57:99:0,114,1710 0/0:27,0:27:60:0,60,900 0/1:47,48:95:99:1413,0,1299 0/0:26,0:26:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:32,0:32:60:0,60,900 0/0:29,0:29:71:0,71,1170 0/0:31,0:31:64:0,64,990 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:66:0,66,1035 0/0:25,0:25:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:33,0:33:66:0,66,990 0/0:38,0:38:81:0,81,1215 0/0:37,0:37:93:0,93,1395 0/0:37,0:37:84:0,84,1260 0/0:40,0:40:75:0,75,1125 0/0:34,0:34:60:0,60,900 0/0:30,0:30:63:0,63,945 0/1:72,53:125:99:1510,0,1825 0/0:31,0:31:63:0,63,945 0/0:56,0:56:99:0,114,1710 0/0:63,0:63:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:37,0:37:81:0,81,1215 0/0:36,0:36:84:0,84,1260 0/0:41,0:41:84:0,84,1260 0/0:25,0:25:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:34,0:34:69:0,69,1035 0/0:45,0:45:99:0,102,1530 0/0:35,0:35:90:0,90,1350 0/0:46,0:46:99:0,114,1710 0/0:40,0:40:93:0,93,1395 0/0:35,0:35:69:0,69,1170 0/0:44,0:44:99:0,105,1575 0/0:30,0:30:72:0,72,1080 0/0:34,0:34:77:0,77,1260 0/0:28,0:28:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:34,0:34:84:0,84,1260 0/0:38,0:38:87:0,87,1305 0/0:53,0:53:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:47,0:47:96:0,96,1440 0/0:37,0:37:87:0,87,1305 0/0:31,0:31:69:0,69,1035 0/0:43,0:43:99:0,99,1485 0/0:58,0:58:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/0:40,0:40:87:0,87,1424 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:30,0:30:61:0,61,990 0/0:41,0:41:87:0,87,1305 0/0:27,0:27:63:0,63,945 0/0:35,0:35:78:0,78,1170 0/0:30,0:30:66:0,66,990 0/0:34,0:34:84:0,84,1260 0/0:31,0:31:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 1/1:2,151:153:99:5441,394,0 0/1:77,64:141:99:1676,0,1884 0/1:72,58:130:99:1752,0,1740 0/0:31,0:31:72:0,72,1080 0/0:52,0:52:99:0,120,1800 0/0:29,0:29:60:0,60,900 0/1:50,65:115:99:1751,0,1191 0/1:67,59:126:99:1582,0,1802 0/1:46,38:84:99:1152,0,1324 0/1:72,56:128:99:1539,0,1773 0/1:63,65:128:99:1758,0,1518 0/0:24,0:24:60:0,60,900 0/0:30,0:30:63:0,63,945 0/1:50,38:88:99:1038,0,1389 0/0:30,0:30:66:0,66,990 +20 16021855 rs114484322 A T 7346.45 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.762;AN=200;InbreedingCoeff=-0.0125;AF=0.012;GQ_STDDEV=57.02;FS=9.696;DP=20047;GQ_MEAN=66.91;POSITIVE_TRAIN_SITE;VQSLOD=2.22;ClippingRankSum=-0.619;BaseQRankSum=-0.465;MLEAF=0.012;MLEAC=21;MQ=60.0;QD=10.27;DB;MQRankSum=-0.044;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,780 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,719 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,721 0/0:23,0:23:63:0,63,945 0/0:20,0:20:60:0,60,699 0/0:20,0:20:60:0,60,732 0/0:22,0:22:60:0,60,870 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,782 0/0:20,0:20:60:0,60,637 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,822 0/0:22,0:22:63:0,63,911 0/0:20,0:20:60:0,60,644 0/0:26,0:26:60:0,60,900 0/1:12,14:26:99:432,0,340 0/0:22,0:22:60:0,60,829 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,801 0/0:23,0:23:60:0,60,900 0/1:23,14:37:99:354,0,722 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,767 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,720 0/0:31,0:31:75:0,75,1125 0/0:43,0:43:99:0,105,1575 0/0:36,0:36:78:0,78,1170 0/0:21,0:21:60:0,60,893 0/0:22,0:22:60:0,60,849 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:24,0:24:63:0,63,927 0/0:27,0:27:66:0,66,872 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:28,0:28:75:0,75,1125 0/0:30,0:30:72:0,72,1080 0/0:29,0:29:63:0,63,945 0/0:25,0:25:61:0,61,900 0/0:27,0:27:69:0,69,1035 0/0:21,0:21:60:0,60,772 0/0:23,0:23:60:0,60,900 0/0:22,0:22:66:0,66,811 0/0:23,0:23:66:0,66,990 0/0:27,0:27:69:0,69,963 0/0:26,0:26:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:32,0:32:72:0,72,1080 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,710 0/0:21,0:21:60:0,60,789 0/0:12,0:12:31:0,31,433 0/0:27,0:27:69:0,69,1035 0/0:23,0:23:63:0,63,935 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,944 0/0:24,0:24:66:0,66,964 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,898 0/0:21,0:21:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,833 0/0:7,0:7:21:0,21,271 0/0:21,0:21:60:0,60,764 0/0:22,0:22:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:28,0:28:78:0,78,1170 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,710 0/0:20,0:20:60:0,60,740 0/0:27,0:27:66:0,66,990 0/0:21,0:21:60:0,60,879 0/0:20,0:20:60:0,60,693 0/0:21,0:21:60:0,60,826 0/0:21,0:21:60:0,60,772 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,756 0/0:21,0:21:63:0,63,743 0/0:24,0:24:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 +20 16025192 . C CT 23299.10 PASS HWP=0.0;AC=36;culprit=QD;MQ0=0;ReadPosRankSum=-0.177;AN=200;InbreedingCoeff=0.0768;AF=0.169;GQ_STDDEV=42.52;FS=0.0;DP=24619;GQ_MEAN=33.54;VQSLOD=3.5;ClippingRankSum=0.148;BaseQRankSum=0.212;MLEAF=0.174;MLEAC=302;MQ=59.13;QD=1.96;MQRankSum=0.254;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:14,6:25:66:66,0,345 0/0:11,3:18:0:0,0,276 0/0:21,0:21:29:0,29,585 0/0:27,0:30:81:0,81,692 0/1:16,4:20:42:42,0,313 0/0:29,0:29:0:0,0,886 0/0:42,0:42:0:0,0,824 0/0:16,0:19:47:0,47,405 0/1:19,7:31:54:54,0,478 0/0:24,0:24:0:0,0,687 0/0:25,0:25:0:0,0,699 0/0:15,4:22:0:0,0,363 0/1:22,3:25:3:3,0,470 0/0:28,0:31:84:0,84,734 0/1:14,7:21:99:114,0,258 0/0:24,3:32:19:0,19,602 0/0:34,0:34:0:0,0,1045 0/0:38,0:44:99:0,113,970 0/1:15,5:20:53:53,0,285 0/1:25,4:29:16:16,0,537 0/0:30,4:34:0:0,0,653 0/0:38,0:38:0:0,0,1006 0/1:22,6:28:79:79,0,471 0/1:17,4:21:40:40,0,348 0/0:17,0:22:51:0,51,440 0/1:17,5:22:54:54,0,337 0/0:22,0:22:0:0,0,466 0/0:26,0:26:0:0,0,748 0/0:16,5:27:0:0,0,401 0/0:16,0:16:0:0,0,342 0/1:11,8:23:99:122,0,262 0/0:24,0:28:72:0,72,607 0/0:50,0:50:0:0,0,1621 0/1:22,3:25:2:2,0,501 0/0:36,0:41:99:0,107,929 0/0:8,0:8:0:0,0,68 0/0:26,0:26:0:0,0,845 0/1:19,0:31:64:64,0,465 0/1:22,3:25:4:4,0,454 0/0:38,0:38:0:0,0,676 0/0:29,0:29:0:0,0,697 0/0:18,0:22:54:0,54,455 0/1:23,4:27:24:24,0,474 0/1:9,3:12:42:42,0,185 0/0:24,3:33:20:0,20,612 0/1:31,4:45:91:91,0,720 0/0:17,0:20:51:0,51,432 0/0:21,0:21:0:0,0,568 0/0:45,3:48:99:0,136,1552 0/1:28,7:35:75:75,0,581 0/0:11,0:16:32:0,32,274 0/0:24,0:24:0:0,0,621 0/0:35,0:35:29:0,29,675 0/1:18,3:21:15:15,0,377 0/0:27,4:35:16:0,16,661 0/0:27,0:30:81:0,81,706 0/0:40,0:40:0:0,0,1199 0/1:24,4:28:21:21,0,486 0/0:28,0:28:0:0,0,834 0/1:28,6:39:24:24,0,663 0/1:15,10:25:99:163,0,288 0/1:20,4:24:31:31,0,420 0/1:31,5:40:9:9,0,735 0/0:35,0:35:0:0,0,1038 0/1:13,10:23:99:158,0,257 0/0:27,4:37:7:0,7,663 0/1:12,3:18:25:25,0,274 0/0:11,0:11:0:0,0,171 0/1:28,4:32:8:8,0,606 0/0:19,0:19:21:0,21,675 0/1:19,5:27:51:51,0,436 0/1:13,3:20:41:41,0,312 0/0:31,3:34:31:0,31,662 0/0:20,0:24:60:0,60,505 0/1:6,11:17:91:234,0,91 0/1:17,6:23:88:88,0,327 0/0:18,0:22:53:0,53,432 0/0:27,0:27:0:0,0,847 0/0:24,0:24:0:0,0,704 0/0:31,0:31:8:0,8,991 0/0:20,0:20:0:0,0,505 0/0:17,0:17:10:0,10,603 0/0:18,0:18:0:0,0,455 0/1:21,4:25:29:29,0,444 0/0:21,0:21:20:0,20,630 0/0:41,0:41:0:0,0,1245 0/0:20,0:20:0:0,0,616 0/0:27,0:27:0:0,0,802 0/0:24,2:29:35:0,35,609 0/0:29,0:34:87:0,87,743 0/0:22,0:22:0:0,0,751 0/1:11,7:18:99:125,0,234 0/1:8,3:11:44:44,0,161 0/0:11,0:11:0:0,0,299 0/0:18,0:23:53:0,53,452 0/1:14,0:20:17:17,0,332 0/0:16,0:16:6:0,6,561 0/0:19,0:19:0:0,0,481 0/1:11,3:14:36:36,0,247 0/0:23,0:28:68:0,68,583 +20 16025192 . CT C 23299.10 PASS HWP=0.0;AC=18;culprit=QD;MQ0=0;ReadPosRankSum=-0.177;AN=200;InbreedingCoeff=0.0768;AF=0.111;GQ_STDDEV=42.52;FS=0.0;DP=24619;GQ_MEAN=33.54;VQSLOD=3.5;ClippingRankSum=0.148;BaseQRankSum=0.212;MLEAF=0.111;MLEAC=194;MQ=59.13;QD=1.96;MQRankSum=0.254;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:14,5:25:0:0,0,421 0/1:11,4:18:43:43,0,352 0/0:21,0:21:29:0,29,585 0/0:27,3:30:9:0,9,610 0/0:16,0:20:48:0,48,373 0/0:29,0:29:0:0,0,886 0/0:42,0:42:0:0,0,824 0/1:16,3:19:24:24,0,348 0/0:19,5:31:0:0,0,550 0/0:24,0:24:0:0,0,687 0/0:25,0:25:0:0,0,699 0/1:15,3:22:36:36,0,403 0/0:22,0:25:66:0,66,545 0/0:28,3:31:13:0,13,653 0/0:14,0:21:42:0,42,321 0/1:24,5:32:5:5,0,697 0/0:34,0:34:0:0,0,1045 0/0:38,6:44:4:0,4,842 0/0:15,0:20:45:0,45,344 0/0:25,0:29:75:0,75,625 0/0:30,0:34:91:0,91,757 0/0:38,0:38:0:0,0,1006 0/0:22,0:28:67:0,67,558 0/0:17,0:21:52:0,52,413 0/1:17,5:22:59:59,0,372 0/0:17,0:22:51:0,51,403 0/0:22,0:22:0:0,0,466 0/0:26,0:26:0:0,0,748 0/1:16,6:27:70:70,0,477 0/0:16,0:16:0:0,0,342 0/0:11,4:23:0:0,0,367 0/1:24,4:28:7:7,0,523 0/0:50,0:50:0:0,0,1621 0/0:22,0:25:67:0,67,577 0/1:36,5:41:12:12,0,805 0/0:8,0:8:0:0,0,68 0/0:26,0:26:0:0,0,845 0/0:19,6:31:0:0,0,560 0/0:22,0:25:65:0,65,529 0/0:38,0:38:0:0,0,676 0/0:29,0:29:0:0,0,697 0/1:18,4:22:41:41,0,388 0/0:23,0:27:69:0,69,555 0/0:9,0:12:27:0,27,221 0/1:24,6:33:47:47,0,676 0/0:31,10:45:56:0,56,959 0/1:17,3:20:21:21,0,372 0/0:21,0:21:0:0,0,568 0/0:45,0:48:99:0,136,1552 0/0:28,0:35:85:0,85,687 0/1:11,5:16:70:70,0,227 0/0:24,0:24:0:0,0,621 0/0:35,0:35:29:0,29,675 0/0:18,0:21:54:0,54,441 0/0:27,4:35:11:0,11,774 0/0:27,3:30:9:0,9,624 0/0:40,0:40:0:0,0,1199 0/0:24,0:28:71:0,71,570 0/0:28,0:28:0:0,0,834 0/0:28,5:39:0:0,0,763 0/0:15,0:25:45:0,45,362 0/0:20,0:24:61:0,61,493 0/0:31,4:40:33:0,33,829 0/0:35,0:35:0:0,0,1038 0/0:13,0:23:39:0,39,325 0/1:27,6:37:45:45,0,687 0/0:12,3:18:0:0,0,319 0/0:11,0:11:0:0,0,171 0/0:28,0:32:84:0,84,703 0/0:19,0:19:21:0,21,675 0/0:19,3:27:24:0,24,518 0/0:13,4:20:0:0,0,386 0/0:31,0:34:92:0,92,732 0/1:20,4:24:19:19,0,432 0/0:6,0:17:19:0,19,143 0/0:17,0:23:51:0,51,396 0/1:18,4:22:42:42,0,366 0/0:27,0:27:0:0,0,847 0/0:24,0:24:0:0,0,704 0/0:31,0:31:8:0,8,991 0/0:20,0:20:0:0,0,505 0/0:17,0:17:10:0,10,603 0/0:18,0:18:0:0,0,455 0/0:21,0:25:63:0,63,520 0/0:21,0:21:20:0,20,630 0/0:41,0:41:0:0,0,1245 0/0:20,0:20:0:0,0,616 0/0:27,0:27:0:0,0,802 0/0:24,3:29:18:0,18,675 0/1:29,5:34:16:16,0,640 0/0:22,0:22:0:0,0,751 0/0:11,0:18:34:0,34,288 0/0:8,0:11:24:0,24,195 0/0:11,0:11:0:0,0,299 0/1:18,5:23:65:65,0,382 0/0:14,3:20:42:0,42,350 0/0:16,0:16:6:0,6,561 0/0:19,0:19:0:0,0,481 0/0:11,0:14:33:0,33,289 0/1:23,5:28:50:50,0,499 +20 16025205 . TC T 37.39 VQSRTrancheINDEL97.00to99.00 HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.629;AN=200;InbreedingCoeff=-0.0017;AF=0.001149;GQ_STDDEV=14.69;FS=3.632;DP=23991;GQ_MEAN=59.34;POSITIVE_TRAIN_SITE;VQSLOD=0.412;ClippingRankSum=0.021;BaseQRankSum=1.46;MLEAF=0.001149;MLEAC=2;MQ=59.46;QD=0.57;MQRankSum=0.496;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:34,0:34:28:0,28,1017 0/0:31,0:31:60:0,60,900 0/0:21,0:21:29:0,29,585 0/0:25,0:25:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:30,0:30:72:0,72,1080 0/0:39,0:39:72:0,72,1080 0/0:22,0:22:60:0,60,771 0/0:34,0:34:66:0,66,990 0/0:27,0:27:46:0,46,835 0/0:29,0:29:60:0,60,900 0/0:33,0:33:78:0,78,1170 0/0:25,0:25:60:0,60,900 0/0:33,0:33:62:0,62,1055 0/0:30,0:30:69:0,69,1035 0/0:39,0:39:87:0,87,1305 0/0:26,0:26:62:0,62,990 0/0:48,0:48:68:0,68,1575 0/0:32,0:32:63:0,63,990 0/0:36,0:36:84:0,84,1260 0/0:35,0:35:69:0,69,1035 0/0:34,4:38:22:0,22,1073 0/0:35,0:35:81:0,81,1215 0/0:32,0:32:60:0,60,900 0/0:36,0:36:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:65:0,65,944 0/0:30,0:30:63:0,63,945 0/0:34,0:34:60:0,60,1143 0/1:24,7:31:69:69,0,743 0/0:38,0:38:72:0,72,1080 0/0:34,0:34:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:37,0:37:69:0,69,1207 0/0:26,0:26:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:34,0:34:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:21,0:21:60:0,60,714 0/0:32,0:32:60:0,60,900 0/1:28,7:35:45:45,0,885 0/0:28,0:28:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:36,0:36:81:0,81,1215 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:48,0:48:99:0,111,1665 0/0:30,0:30:60:0,60,900 0/0:33,0:33:67:0,67,1035 0/0:36,0:36:77:0,77,1170 0/0:28,0:28:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:33,0:33:63:0,63,1189 0/0:24,0:24:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:28,0:28:60:0,60,900 0/0:26,0:26:54:0,54,810 0/0:38,0:38:81:0,81,1215 0/0:26,0:26:60:0,60,900 0/0:34,0:34:63:0,63,945 0/0:35,0:35:62:0,62,1139 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:43:0,43,675 0/0:22,0:22:60:0,60,900 0/0:21,0:21:27:0,27,540 0/0:17,0:17:31:0,31,585 0/0:23,0:23:63:0,63,945 0/0:33,0:33:63:0,63,945 0/0:22,0:22:60:0,60,897 0/0:38,0:38:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:36,0:36:63:0,63,945 0/0:24,0:24:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:15,0:15:30:0,30,450 0/0:12,0:12:30:0,30,450 0/0:24,0:24:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:22,0:22:60:0,60,757 0/0:15,0:15:42:0,42,483 0/0:21,0:21:60:0,60,900 +20 16025289 rs80044408 G T 8447.92 PASS HWP=1.0;AC=6;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.116;AN=200;InbreedingCoeff=-0.0114;AF=0.011;GQ_STDDEV=61.64;FS=2.635;DP=23621;GQ_MEAN=67.58;POSITIVE_TRAIN_SITE;VQSLOD=3.39;ClippingRankSum=0.53;BaseQRankSum=-1.736;MLEAF=0.011;MLEAC=19;MQ=59.25;QD=11.73;DB;MQRankSum=0.501;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:30,0:30:72:0,72,1080 0/0:39,0:39:72:0,72,1080 0/0:22,0:22:60:0,60,771 0/0:34,0:34:66:0,66,990 0/0:28,0:28:69:0,69,1035 0/0:27,0:27:66:0,66,985 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:62:0,62,1055 0/0:30,0:30:69:0,69,1035 0/0:39,0:39:87:0,87,1305 0/0:26,0:26:62:0,62,990 0/0:48,0:48:68:0,68,1575 0/0:32,0:32:63:0,63,990 0/0:36,0:36:84:0,84,1260 0/0:35,0:35:69:0,69,1035 0/0:38,0:38:90:0,90,1350 0/0:35,0:35:81:0,81,1215 0/0:32,0:32:60:0,60,900 0/0:36,0:36:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:65:0,65,944 0/0:30,0:30:63:0,63,945 0/0:38,0:38:81:0,81,1215 0/0:28,0:28:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:34,0:34:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:37,0:37:69:0,69,1207 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:16,0:16:21:0,21,315 0/0:12,0:12:24:0,24,360 0/0:14,0:14:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:30,0:30:63:0,63,945 0/1:13,6:19:99:159,0,462 0/0:29,0:29:62:0,62,945 0/0:29,0:29:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:18,16:34:99:482,0,598 0/0:25,0:25:60:0,60,900 0/0:9,0:9:21:0,21,315 0/1:10,16:26:99:466,0,306 0/0:36,0:36:77:0,77,1170 0/0:28,0:28:60:0,60,900 0/0:14,0:14:21:0,21,315 0/0:33,0:33:63:0,63,1189 0/0:16,0:16:21:0,21,315 0/1:9,9:18:99:261,0,296 0/0:28,0:28:60:0,60,900 0/0:13,0:13:24:0,24,360 0/0:38,0:38:81:0,81,1215 0/0:10,0:10:21:0,21,315 0/0:34,0:34:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:13,0:13:24:0,24,360 0/1:11,19:30:99:581,0,380 0/1:12,8:20:99:226,0,435 0/0:14,0:14:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:18,0:18:36:0,36,540 0/0:8,0:8:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:38,0:38:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:36,0:36:63:0,63,945 0/0:24,0:24:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:36,0:36:84:0,84,1149 0/0:31,0:31:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:21,0:21:60:0,60,900 +20 16223922 rs1541065 T C 175453.00 PASS HWP=0.0;AC=101;culprit=MQ;MQ0=0;ReadPosRankSum=0.296;AN=188;InbreedingCoeff=0.2111;AF=0.687;GQ_STDDEV=65.38;FS=0.568;DP=7661;GQ_MEAN=47.28;POSITIVE_TRAIN_SITE;VQSLOD=4.38;ClippingRankSum=0.244;BaseQRankSum=0.727;MLEAF=0.722;MLEAC=1211;MQ=60.0;QD=26.73;DB;MQRankSum=0.263;CCC=1678;NCC=31 GT:AD:DP:GQ:PL 0/0:9,0:9:0:0,0,143 0/1:6,4:10:99:100,0,175 1/1:0,9:9:27:297,27,0 1/1:0,3:3:9:85,9,0 1/1:0,4:4:12:154,12,0 0/1:8,5:13:99:127,0,272 0/1:1,3:4:23:112,0,23 0/1:4,7:11:99:185,0,126 1/1:0,4:4:12:135,12,0 0/0:4,0:4:0:0,0,83 ./.:1,0:1:.:. 0/1:3,6:9:88:200,0,88 1/1:0,8:8:24:254,24,0 0/1:4,5:9:99:110,0,102 ./.:1,0:1:.:. 1/1:0,8:8:24:278,24,0 1/1:0,10:10:30:331,30,0 0/1:3,6:9:84:133,0,84 0/1:4,3:7:92:92,0,122 1/1:0,3:3:9:112,9,0 1/1:0,8:8:24:282,24,0 0/1:6,7:13:99:187,0,192 0/1:5,4:9:99:130,0,139 0/1:16,12:28:99:281,0,449 0/0:20,0:20:57:0,57,855 1/1:0,3:3:9:119,9,0 0/0:5,0:5:0:0,0,114 0/0:12,0:12:27:0,27,390 0/1:5,4:9:99:101,0,167 0/1:6,6:12:99:172,0,174 1/1:0,10:10:30:368,30,0 1/1:0,14:14:42:513,42,0 0/1:8,8:16:99:230,0,213 0/1:3,8:11:91:234,0,91 1/1:0,9:9:27:368,27,0 1/1:0,5:5:15:216,15,0 1/1:0,15:15:45:489,45,0 0/0:7,0:7:21:0,21,230 ./.:4,0:4:.:. 1/1:0,7:7:21:243,21,0 1/1:0,4:4:12:152,12,0 0/0:3,0:3:9:0,9,109 1/1:0,9:9:27:339,27,0 0/0:6,0:6:0:0,0,27 0/0:8,0:8:21:0,21,304 0/0:4,0:4:9:0,9,125 0/1:7,10:17:99:326,0,137 0/0:12,0:12:21:0,21,315 0/1:7,3:10:90:90,0,257 0/0:8,0:8:0:0,0,213 0/1:3,5:8:88:148,0,88 1/1:0,4:4:12:156,12,0 ./.:6,0:6:.:. 0/1:3,7:10:87:241,0,87 0/0:7,0:7:0:0,0,83 0/1:5,4:9:99:130,0,142 0/1:9,6:15:99:154,0,280 0/0:7,0:7:21:0,21,241 0/0:9,0:9:21:0,21,315 0/0:2,0:2:0:0,0,2 0/0:2,0:2:6:0,6,72 0/0:3,0:3:6:0,6,89 0/0:8,0:8:21:0,21,289 0/0:5,0:5:12:0,12,180 1/1:0,6:6:18:248,18,0 0/1:1,10:11:6:299,0,6 0/0:1,0:1:3:0,3,18 0/0:3,0:3:0:0,0,48 0/0:5,0:5:9:0,9,135 1/1:0,4:4:12:176,12,0 1/1:0,11:11:33:434,33,0 1/1:0,3:3:9:130,9,0 0/1:5,4:9:99:146,0,147 ./.:2,0:2:.:. 0/1:1,3:4:30:122,0,30 0/1:5,5:10:99:141,0,173 0/1:2,4:6:49:120,0,49 0/0:2,0:2:6:0,6,74 0/1:1,3:4:27:119,0,27 0/0:6,0:6:0:0,0,45 0/1:4,5:9:99:155,0,101 0/1:6,3:9:59:59,0,109 0/0:3,0:3:9:0,9,112 0/0:7,0:7:0:0,0,161 1/1:0,8:8:24:270,24,0 1/1:0,8:8:24:234,24,0 0/0:4,0:4:0:0,0,46 0/1:1,9:10:11:252,0,11 1/1:0,3:3:9:114,9,0 0/1:7,5:12:99:176,0,218 1/1:1,12:13:1:336,1,0 1/1:0,5:5:15:174,15,0 1/1:0,5:5:15:221,15,0 ./.:1,0:1:.:. 1/1:0,10:10:30:342,30,0 1/1:0,5:5:15:143,15,0 1/1:0,7:7:21:225,21,0 1/1:0,3:3:9:133,9,0 1/1:0,3:3:9:94,9,0 1/1:0,8:8:24:305,24,0 +20 16223957 rs1000121 T C 97989.20 PASS HWP=0.0;AC=45;culprit=MQ;MQ0=0;ReadPosRankSum=0.248;AN=190;InbreedingCoeff=0.108;AF=0.344;GQ_STDDEV=68.4;FS=0.518;DP=8309;GQ_MEAN=54.36;POSITIVE_TRAIN_SITE;VQSLOD=5.33;ClippingRankSum=0.068;BaseQRankSum=0.851;MLEAF=0.37;MLEAC=632;MQ=60.0;QD=19.0;DB;MQRankSum=0.185;CCC=1708;NCC=16 GT:AD:DP:GQ:PL 0/0:9,0:9:0:0,0,80 0/0:8,0:8:21:0,21,315 0/1:2,5:7:28:120,0,28 ./.:2,0:2:.:. 1/1:0,6:6:18:211,18,0 0/1:7,8:15:99:217,0,206 0/0:4,0:4:0:0,0,71 0/0:11,0:11:29:0,29,362 0/0:4,0:4:9:0,9,125 0/1:5,3:8:66:66,0,139 1/1:0,5:5:15:143,15,0 0/1:3,7:10:84:186,0,84 1/1:0,7:7:21:262,21,0 0/0:7,0:7:21:0,21,234 ./.:3,0:3:.:. 1/1:0,7:7:21:274,21,0 0/1:4,11:15:80:294,0,80 0/0:10,0:10:21:0,21,305 0/0:7,0:7:21:0,21,268 1/1:0,7:7:21:188,21,0 0/0:7,0:7:0:0,0,85 0/0:12,0:12:30:0,30,450 0/1:8,6:14:99:132,0,223 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 ./.:2,0:2:.:. 0/0:8,0:8:24:0,24,294 0/0:12,0:12:27:0,27,390 0/1:8,3:11:86:86,0,234 0/0:9,0:9:21:0,21,315 0/1:6,7:13:99:215,0,173 1/1:0,15:15:45:518,45,0 0/0:10,0:10:21:0,21,315 0/1:5,9:14:99:273,0,117 1/1:0,13:13:39:431,39,0 0/1:7,8:15:99:153,0,139 0/1:13,6:19:99:172,0,306 0/0:14,0:14:24:0,24,360 0/0:7,0:7:21:0,21,276 0/0:8,0:8:21:0,21,315 0/0:4,0:4:12:0,12,156 0/0:4,0:4:6:0,6,90 0/0:4,0:4:12:0,12,151 0/0:6,0:6:0:0,0,41 0/0:8,0:8:21:0,21,304 0/0:4,0:4:9:0,9,125 0/0:11,0:11:21:0,21,315 0/0:12,0:12:21:0,21,315 0/0:8,0:8:21:0,21,310 0/0:7,0:7:21:0,21,264 0/1:5,5:10:99:166,0,133 0/0:3,0:3:6:0,6,90 0/0:7,0:7:21:0,21,208 0/0:10,0:10:27:0,27,355 0/1:3,4:7:92:152,0,92 0/0:8,0:8:21:0,21,242 0/1:11,8:19:99:193,0,304 0/0:3,0:3:9:0,9,114 0/0:9,0:9:21:0,21,315 0/0:2,0:2:6:0,6,76 0/0:2,0:2:6:0,6,72 0/0:3,0:3:6:0,6,89 0/0:8,0:8:21:0,21,289 0/0:5,0:5:12:0,12,180 0/0:7,0:7:21:0,21,264 0/0:8,0:8:21:0,21,285 0/0:2,0:2:6:0,6,68 0/0:2,0:2:6:0,6,73 0/0:7,0:7:21:0,21,288 ./.:4,0:4:.:. 0/0:12,0:12:24:0,24,360 0/0:3,0:3:9:0,9,102 0/0:9,0:9:21:0,21,307 0/0:4,0:4:0:0,0,41 0/0:4,0:4:9:0,9,135 0/0:9,0:9:21:0,21,289 0/0:7,0:7:21:0,21,231 0/0:2,0:2:6:0,6,74 0/1:4,6:10:97:157,0,97 0/1:2,3:5:64:108,0,64 0/0:9,0:9:21:0,21,284 0/0:8,0:8:18:0,18,270 0/0:3,0:3:9:0,9,112 0/0:8,0:8:21:0,21,253 1/1:0,9:9:27:316,27,0 1/1:0,7:7:21:269,21,0 0/0:6,0:6:18:0,18,199 0/0:7,0:7:21:0,21,211 1/1:0,8:8:24:223,24,0 0/1:8,5:13:99:173,0,211 1/1:1,21:22:26:645,26,0 1/1:0,8:8:24:232,24,0 0/0:5,0:5:0:0,0,38 ./.:1,0:1:.:. 0/0:9,0:9:24:0,24,307 1/1:0,8:8:24:269,24,0 0/0:7,0:7:0:0,0,76 0/0:2,0:2:6:0,6,71 0/0:3,0:3:9:0,9,86 1/1:0,13:13:39:416,39,0 +20 16254033 rs181743010 G A 1553.31 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=2.38;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=43.08;FS=1.319;DP=28263;GQ_MEAN=73.19;VQSLOD=2.3;ClippingRankSum=-1.554;BaseQRankSum=-2.014;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=9.53;DB;MQRankSum=0.142;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:66:0,66,990 0/0:24,0:24:63:0,63,945 0/0:30,0:30:78:0,78,1170 0/0:27,0:27:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:37,0:37:67:0,67,1035 0/0:34,0:34:69:0,69,1035 0/0:28,0:28:47:0,47,887 0/0:30,0:30:72:0,72,1080 0/0:25,0:25:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:26,0:26:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:28,0:28:69:0,69,1035 0/0:74,0:74:99:0,120,1800 0/0:69,0:69:99:0,111,1665 0/0:28,0:28:75:0,75,1071 0/0:31,0:31:66:0,66,990 0/0:32,0:32:66:0,66,990 0/0:27,0:27:69:0,69,1032 0/0:32,0:32:78:0,78,1170 0/0:39,0:39:87:0,87,1305 0/0:32,0:32:75:0,75,1125 0/0:44,0:44:97:0,97,1575 0/0:46,0:46:81:0,81,1215 0/0:44,0:44:99:0,102,1530 0/0:32,0:32:72:0,72,1080 0/0:31,0:31:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:35,0:35:81:0,81,1215 0/0:28,0:28:60:0,60,900 0/0:29,0:29:62:0,62,1080 0/0:25,0:25:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:29,0:29:66:0,66,990 0/0:46,0:46:99:0,99,1485 0/0:28,0:28:66:0,66,990 0/0:53,0:53:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:30,0:30:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:26,0:26:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:32,0:32:81:0,81,1215 0/0:32,0:32:69:0,69,1035 0/0:42,0:42:99:0,105,1575 0/0:41,0:41:84:0,84,1260 0/0:32,0:32:69:0,69,1035 0/0:37,0:37:84:0,84,1260 0/0:30,0:30:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:45,0:45:96:0,96,1440 0/0:25,0:25:63:0,63,945 0/0:34,0:34:71:0,71,1125 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:37,0:37:77:0,77,1458 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:28,0:28:66:0,66,990 0/0:32,0:32:78:0,78,1170 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:29,0:29:65:0,65,1151 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:75:0,75,1125 0/0:33,0:33:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:32,0:32:60:0,60,1035 0/1:70,47:117:99:1192,0,2110 0/0:26,0:26:60:0,60,900 0/0:34,0:34:69:0,69,1035 0/0:31,0:31:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 +20 16347823 rs3746782 G C 2993.33 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.56;AN=200;InbreedingCoeff=-0.0024;AF=0.002299;GQ_STDDEV=47.74;FS=1.762;DP=19545;GQ_MEAN=63.75;POSITIVE_TRAIN_SITE;VQSLOD=4.79;ClippingRankSum=-0.542;BaseQRankSum=-2.093;MLEAF=0.002299;MLEAC=4;MQ=59.71;QD=14.67;DB;MQRankSum=0.747;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:21,0:21:60:0,60,757 0/0:20,0:20:60:0,60,740 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,845 0/0:21,0:21:60:0,60,809 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,737 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,805 0/0:22,0:22:66:0,66,788 0/0:20,0:20:60:0,60,698 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,843 0/0:28,0:28:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,699 0/0:21,0:21:60:0,60,900 0/0:21,0:21:61:0,61,750 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,874 0/0:20,0:20:60:0,60,733 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,832 0/0:22,0:22:63:0,63,826 0/0:25,0:25:60:0,60,900 0/0:21,0:21:63:0,63,797 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,744 0/0:30,0:30:63:0,63,945 0/0:22,0:22:63:0,63,925 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,797 0/0:22,0:22:60:0,60,898 0/0:30,0:30:63:0,63,945 0/0:24,0:24:60:0,60,873 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:25,0:25:62:0,62,983 0/0:24,0:24:60:0,60,900 0/0:29,0:29:68:0,68,1170 0/0:22,0:22:60:0,60,879 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,738 0/0:21,0:21:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:20,0:20:60:0,60,726 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,807 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:68:0,68,1098 0/0:22,0:22:60:0,60,860 0/0:21,0:21:60:0,60,786 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,710 0/0:22,0:22:60:0,60,825 0/0:23,0:23:60:0,60,898 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,804 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:22,0:22:63:0,63,927 0/0:21,0:21:60:0,60,773 0/0:20,0:20:60:0,60,685 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,881 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,740 0/0:28,0:28:73:0,73,1170 0/0:20,0:20:60:0,60,735 0/0:24,0:24:60:0,60,900 0/0:22,0:22:61:0,61,945 0/0:23,0:23:60:0,60,802 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,810 0/1:15,15:30:99:509,0,525 0/0:23,0:23:60:0,60,900 0/0:25,0:25:61:0,61,945 0/0:21,0:21:60:0,60,746 0/0:22,0:22:60:0,60,854 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:20,0:20:60:0,60,667 0/0:22,0:22:60:0,60,773 0/0:21,0:21:63:0,63,817 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,901 +20 16347929 rs73093402 C A 91893.60 PASS HWP=1.0;AC=7;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.662;AN=200;InbreedingCoeff=-0.0229;AF=0.022;GQ_STDDEV=499.87;FS=0.0;DP=25884;GQ_MEAN=160.77;POSITIVE_TRAIN_SITE;VQSLOD=5.18;ClippingRankSum=-0.055;BaseQRankSum=-3.054;MLEAF=0.022;MLEAC=39;MQ=59.63;QD=12.94;DB;MQRankSum=0.531;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:21,0:21:60:0,60,757 0/0:20,0:20:60:0,60,740 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,845 0/0:21,0:21:60:0,60,809 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,737 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,805 0/0:22,0:22:66:0,66,788 0/0:20,0:20:60:0,60,698 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,843 0/0:28,0:28:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,699 0/1:72,60:132:99:1753,0,2061 0/0:21,0:21:61:0,61,750 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,874 0/1:157,161:318:99:4592,0,4910 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,832 0/1:112,94:206:99:2494,0,3345 0/0:25,0:25:60:0,60,900 0/0:21,0:21:63:0,63,797 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,744 0/0:30,0:30:63:0,63,945 0/0:22,0:22:63:0,63,925 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,797 0/0:22,0:22:60:0,60,898 0/0:30,0:30:63:0,63,945 0/0:24,0:24:60:0,60,873 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:25,0:25:62:0,62,983 0/0:24,0:24:60:0,60,900 0/0:29,0:29:68:0,68,1170 0/0:22,0:22:60:0,60,879 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,738 0/0:21,0:21:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:20,0:20:60:0,60,726 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,807 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:90,66:156:99:1818,0,2721 0/0:22,0:22:60:0,60,860 0/0:21,0:21:60:0,60,786 0/0:23,0:23:60:0,60,900 0/1:94,63:157:99:1580,0,3031 0/0:22,0:22:60:0,60,825 0/0:23,0:23:60:0,60,898 0/0:31,0:31:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/1:143,113:256:99:3106,0,4096 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:22,0:22:63:0,63,927 0/0:21,0:21:60:0,60,773 0/0:20,0:20:60:0,60,685 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,881 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,740 0/1:62,56:118:99:1524,0,2107 0/0:20,0:20:60:0,60,735 0/0:24,0:24:60:0,60,900 0/0:22,0:22:61:0,61,945 0/0:23,0:23:60:0,60,802 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,810 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:61:0,61,945 0/0:21,0:21:60:0,60,746 0/0:22,0:22:60:0,60,854 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:20,0:20:60:0,60,667 0/0:22,0:22:60:0,60,773 0/0:21,0:21:63:0,63,817 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,901 +20 16348291 rs41306786 T G 17073.80 PASS HWP=1.0;AC=7;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.144;AN=200;InbreedingCoeff=-0.0234;AF=0.022;GQ_STDDEV=83.98;FS=3.332;DP=18724;GQ_MEAN=68.2;POSITIVE_TRAIN_SITE;VQSLOD=3.71;ClippingRankSum=0.163;BaseQRankSum=1.59;MLEAF=0.022;MLEAC=39;MQ=60.0;QD=14.04;DB;MQRankSum=0.193;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:48:0,48,720 0/0:22,0:22:60:0,60,845 0/0:25,0:25:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:11,0:11:30:0,30,384 0/0:22,0:22:66:0,66,788 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,699 0/1:17,18:35:99:495,0,474 0/0:21,0:21:61:0,61,750 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,874 0/1:59,19:78:99:494,0,1801 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,832 0/1:17,14:31:99:411,0,551 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,744 0/0:30,0:30:63:0,63,945 0/0:22,0:22:63:0,63,925 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,797 0/0:22,0:22:60:0,60,898 0/0:30,0:30:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:25,0:25:62:0,62,983 0/0:24,0:24:60:0,60,900 0/0:29,0:29:68:0,68,1170 0/0:22,0:22:60:0,60,879 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,738 0/0:21,0:21:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:14,0:14:34:0,34,518 0/0:12,0:12:22:0,22,468 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,807 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:23,8:31:99:201,0,764 0/0:22,0:22:60:0,60,860 0/0:21,0:21:60:0,60,786 0/0:23,0:23:60:0,60,900 0/1:26,23:49:99:721,0,762 0/0:22,0:22:60:0,60,825 0/0:15,0:15:26:0,26,579 0/0:10,0:10:26:0,26,405 0/0:22,0:22:60:0,60,900 0/0:12,0:12:24:0,24,360 0/1:15,17:32:99:589,0,468 0/0:20,0:20:60:0,60,702 0/0:23,0:23:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:13,0:13:25:0,25,491 0/0:17,0:17:42:0,42,625 0/0:12,0:12:27:0,27,405 0/0:14,0:14:32:0,32,495 0/0:20,0:20:54:0,54,810 0/0:24,0:24:60:0,60,900 0/1:9,8:17:99:266,0,289 0/0:10,0:10:21:0,21,315 0/0:13,0:13:32:0,32,487 0/0:22,0:22:61:0,61,945 0/0:15,0:15:36:0,36,585 0/0:21,0:21:60:0,60,900 0/0:20,0:20:48:0,48,720 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:61:0,61,945 0/0:21,0:21:60:0,60,746 0/0:22,0:22:60:0,60,854 0/0:24,0:24:60:0,60,900 0/0:15,0:15:39:0,39,585 0/0:25,0:25:60:0,60,879 0/0:14,0:14:33:0,33,495 0/0:7,0:7:21:0,21,234 0/0:14,0:14:36:0,36,498 0/0:11,0:11:21:0,21,361 0/0:25,0:25:60:0,60,900 +20 16348476 rs118084641 T C 2566.17 PASS HWP=1.0;AC=5;culprit=MQ;MQ0=0;ReadPosRankSum=0.591;AN=200;InbreedingCoeff=-0.0087;AF=0.006322;GQ_STDDEV=26.45;FS=2.346;DP=15004;GQ_MEAN=43.65;POSITIVE_TRAIN_SITE;VQSLOD=4.18;ClippingRankSum=0.594;BaseQRankSum=-1.604;MLEAF=0.006322;MLEAC=11;MQ=60.0;QD=11.51;DB;MQRankSum=-0.255;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:12,14:26:99:381,0,388 0/1:7,8:15:99:194,0,228 0/0:11,0:11:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:25,0:25:57:0,57,855 0/0:8,0:8:21:0,21,315 0/1:9,7:16:99:178,0,313 0/1:6,9:15:99:260,0,180 0/0:9,0:9:21:0,21,315 0/0:15,0:15:33:0,33,495 0/0:9,0:9:24:0,24,325 0/0:8,0:8:21:0,21,287 0/0:10,0:10:21:0,21,315 0/0:12,0:12:24:0,24,360 0/0:11,0:11:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:9,0:9:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:40,0:40:93:0,93,1395 0/0:22,0:22:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:22,0:22:63:0,63,861 0/1:16,4:20:52:52,0,514 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:22,0:22:63:0,63,925 0/0:29,0:29:69:0,69,1011 0/0:21,0:21:60:0,60,887 0/0:20,0:20:60:0,60,770 0/0:22,0:22:60:0,60,832 0/0:9,0:9:24:0,24,360 0/0:30,0:30:63:0,63,945 0/0:21,0:21:57:0,57,855 0/0:8,0:8:21:0,21,315 0/0:20,0:20:54:0,54,810 0/0:14,0:14:27:0,27,405 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:22,0:22:60:0,60,879 0/0:9,0:9:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:28,0:28:57:0,57,855 0/0:23,0:23:60:0,60,900 0/0:13,0:13:27:0,27,450 0/0:9,0:9:24:0,24,360 0/0:27,0:27:60:0,60,900 0/0:13,0:13:22:0,22,360 0/0:27,0:27:60:0,60,900 0/0:23,0:23:54:0,54,810 0/0:24,0:24:63:0,63,891 0/0:24,0:24:60:0,60,900 0/0:12,0:12:27:0,27,405 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,786 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:11,0:11:24:0,24,360 0/0:8,0:8:21:0,21,315 0/0:10,0:10:26:0,26,405 0/0:22,0:22:60:0,60,900 0/0:15,0:15:21:0,21,315 0/0:14,0:14:30:0,30,450 0/0:27,0:27:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:12,0:12:21:0,21,315 0/0:17,0:17:27:0,27,585 0/0:8,0:8:21:0,21,315 0/0:9,0:9:24:0,24,345 0/0:13,0:13:30:0,30,450 0/0:10,0:10:24:0,24,360 0/0:26,0:26:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:9,0:9:24:0,24,302 0/0:4,0:4:12:0,12,142 0/0:21,0:21:54:0,54,810 0/0:9,0:9:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:9,0:9:20:0,20,328 0/0:25,0:25:61:0,61,945 0/0:23,0:23:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:8,0:8:24:0,24,290 0/0:27,0:27:60:0,60,900 0/0:20,0:20:60:0,60,785 0/0:4,0:4:12:0,12,130 0/0:8,0:8:21:0,21,315 0/0:9,0:9:24:0,24,360 0/0:23,0:23:60:0,60,900 +20 16351329 rs2144893 C T 243287.00 PASS HWP=0.1641;AC=64;culprit=MQ;MQ0=0;ReadPosRankSum=0.322;AN=200;InbreedingCoeff=0.0222;AF=0.449;GQ_STDDEV=116.44;FS=0.0;DP=16059;GQ_MEAN=123.81;POSITIVE_TRAIN_SITE;VQSLOD=6.86;ClippingRankSum=-0.116;BaseQRankSum=1.95;MLEAF=0.457;MLEAC=795;MQ=60.0;QD=21.48;DB;MQRankSum=0.124;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:15,0:15:24:0,24,540 0/0:15,0:15:36:0,36,540 0/0:16,0:16:39:0,39,585 0/1:3,7:10:76:212,0,76 0/1:20,7:27:99:194,0,629 0/1:7,13:20:99:410,0,187 0/0:11,0:11:27:0,27,405 0/0:20,0:20:51:0,51,765 0/0:19,0:19:51:0,51,765 0/1:6,4:10:99:130,0,185 0/1:9,7:16:99:195,0,273 0/1:5,6:11:99:197,0,142 1/1:1,28:29:49:1060,49,0 0/1:6,8:14:99:271,0,166 0/1:15,12:27:99:365,0,398 1/1:0,19:19:57:725,57,0 0/1:8,7:15:99:208,0,237 0/1:11,14:25:99:446,0,283 0/1:9,7:16:99:214,0,247 0/0:29,0:29:60:0,60,900 1/1:0,21:21:63:788,63,0 0/1:12,13:25:99:392,0,322 0/0:21,0:21:60:0,60,900 0/1:3,14:17:70:378,0,70 0/0:12,0:12:27:0,27,405 1/1:0,24:24:72:858,72,0 0/1:7,6:13:99:192,0,169 0/0:14,0:14:30:0,30,495 0/0:34,0:34:78:0,78,1170 0/0:18,0:18:42:0,42,630 0/0:23,0:23:45:0,45,675 0/0:14,0:14:36:0,36,540 0/1:7,15:22:99:469,0,178 0/1:15,13:28:99:401,0,419 0/1:17,13:30:99:357,0,469 0/1:3,5:8:79:174,0,79 0/1:11,3:14:74:74,0,341 0/0:14,0:14:33:0,33,495 0/0:17,0:17:39:0,39,585 0/1:8,11:19:99:337,0,210 0/0:11,0:11:24:0,24,360 0/1:9,11:20:99:344,0,246 0/1:9,5:14:99:144,0,261 0/1:10,10:20:99:330,0,259 0/0:21,0:21:45:0,45,675 0/0:12,0:12:33:0,33,495 0/1:5,10:15:99:327,0,113 0/0:23,0:23:63:0,63,945 0/1:14,17:31:99:561,0,402 0/0:37,0:37:96:0,96,1440 0/0:8,0:8:18:0,18,270 0/1:5,10:15:99:307,0,110 0/1:7,10:17:99:321,0,178 0/1:6,9:15:99:258,0,147 0/1:13,11:24:99:329,0,383 1/1:0,20:20:60:697,60,0 0/0:17,0:17:2:0,2,436 0/1:11,9:20:99:246,0,285 0/0:12,0:12:33:0,33,460 0/1:13,17:30:99:530,0,378 0/1:5,9:14:99:303,0,119 0/1:8,9:17:99:298,0,191 0/0:23,0:23:51:0,51,765 0/0:12,0:12:27:0,27,405 0/1:8,5:13:99:152,0,239 0/0:21,0:21:45:0,45,675 1/1:0,12:12:36:470,36,0 0/1:5,5:10:99:162,0,156 0/0:30,0:30:78:0,78,1170 1/1:0,5:5:15:188,15,0 0/1:5,18:23:82:632,0,82 0/0:7,0:7:15:0,15,225 0/1:14,15:29:99:414,0,416 0/0:10,0:10:24:0,24,360 0/1:5,9:14:99:302,0,123 0/0:8,0:8:21:0,21,315 0/1:8,9:17:99:264,0,238 0/1:8,8:16:99:230,0,247 0/1:7,7:14:99:183,0,212 0/1:5,12:17:99:393,0,125 0/1:6,5:11:99:159,0,189 0/1:6,5:11:99:160,0,186 0/0:7,0:7:12:0,12,180 1/1:0,20:20:60:708,60,0 0/0:14,0:14:30:0,30,450 0/1:4,13:17:82:453,0,82 0/0:8,0:8:21:0,21,292 0/0:1,0:1:3:0,3,41 0/0:23,0:23:45:0,45,675 0/0:28,0:28:66:0,66,990 0/0:14,0:14:30:0,30,450 0/0:11,0:11:24:0,24,360 0/0:14,0:14:36:0,36,540 0/0:4,0:4:6:0,6,90 0/1:7,10:17:99:338,0,205 0/0:4,0:4:9:0,9,135 0/0:8,0:8:21:0,21,315 1/1:0,16:16:48:586,48,0 0/0:7,0:7:15:0,15,225 0/0:13,0:13:27:0,27,405 +20 16354949 rs61738023 C A 77952.50 PASS HWP=0.0227;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.475;AN=200;InbreedingCoeff=0.1043;AF=0.041;GQ_STDDEV=269.73;FS=0.524;DP=38813;GQ_MEAN=158.49;POSITIVE_TRAIN_SITE;VQSLOD=5.78;ClippingRankSum=0.0;BaseQRankSum=-3.649;MLEAF=0.041;MLEAC=71;MQ=59.85;QD=14.35;DB;MQRankSum=0.291;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:80:0,80,1215 0/0:39,0:39:99:0,99,1402 0/0:28,0:28:62:0,62,945 0/0:44,0:44:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:38,0:38:93:0,93,1395 0/0:35,0:35:84:0,84,1260 0/0:29,0:29:69:0,69,1035 0/0:29,0:29:60:0,60,900 0/0:37,0:37:86:0,86,1350 0/0:28,0:28:63:0,63,945 0/0:32,0:32:63:0,63,945 0/0:37,0:37:93:0,93,1395 0/0:49,0:49:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:44,0:44:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:39,0:39:78:0,78,1170 0/0:47,0:47:99:0,108,1620 0/0:41,0:41:84:0,84,1260 0/0:47,0:47:99:0,120,1800 0/0:52,0:52:99:0,99,1485 0/0:43,0:43:93:0,93,1395 0/0:38,0:38:60:0,60,900 0/0:70,0:70:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:54,0:54:99:0,120,1800 0/0:35,0:35:81:0,81,1215 0/0:51,0:51:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:31,0:31:66:0,66,990 0/0:34,0:34:81:0,81,1215 0/0:46,0:46:99:0,117,1755 0/0:43,0:43:96:0,96,1440 0/0:47,0:47:99:0,99,1485 0/0:41,0:41:99:0,105,1575 0/0:45,0:45:99:0,108,1620 0/0:85,0:85:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:40,0:40:90:0,90,1350 0/0:35,0:35:84:0,84,1260 0/0:32,0:32:78:0,78,1170 0/0:45,0:45:99:0,110,1710 0/0:48,0:48:99:0,108,1620 0/0:38,0:38:96:0,96,1440 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,111,1665 0/0:48,0:48:99:0,117,1755 0/0:60,0:60:99:0,120,1800 0/0:34,0:34:78:0,78,1170 0/0:34,0:34:66:0,66,990 0/0:78,0:78:99:0,120,1800 0/0:39,0:39:93:0,93,1395 0/0:41,0:41:93:0,93,1395 0/0:52,0:52:99:0,120,1800 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:72,0:72:99:0,120,1800 0/0:27,0:27:69:0,69,1035 0/0:50,0:50:99:0,108,1620 0/0:30,0:30:78:0,78,1123 0/1:54,66:120:99:1803,0,1861 0/0:37,0:37:90:0,90,1350 0/0:42,0:42:96:0,96,1440 0/0:25,0:25:63:0,63,945 0/1:34,26:60:99:751,0,1100 0/0:27,0:27:81:0,81,951 0/0:34,0:34:73:0,73,1170 0/0:37,0:37:86:0,86,1264 0/0:30,0:30:80:0,80,1075 0/0:20,0:20:60:0,60,733 0/0:29,0:29:75:0,75,1125 0/0:38,0:38:99:0,99,1485 0/0:31,0:31:69:0,69,1035 0/0:50,0:50:99:0,117,1755 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:70,0:70:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:30,0:30:75:0,75,1125 0/0:30,0:30:63:0,63,945 0/0:38,0:38:84:0,84,1284 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:38,0:38:99:0,99,1485 0/0:30,0:30:72:0,72,1080 0/0:41,0:41:99:0,108,1620 +20 16359567 rs6034464 A G 2732790.00 PASS HWP=0.0104;AC=133;culprit=FS;MQ0=0;ReadPosRankSum=0.227;AN=200;InbreedingCoeff=0.0912;AF=0.775;GQ_STDDEV=679.05;FS=0.0;DP=104191;GQ_MEAN=745.65;POSITIVE_TRAIN_SITE;VQSLOD=6.4;ClippingRankSum=-0.053;BaseQRankSum=0.127;MLEAF=0.775;MLEAC=1348;MQ=59.59;QD=26.97;DB;MQRankSum=0.004;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,129:129:99:4441,387,0 1/1:0,155:155:99:5285,466,0 1/1:2,97:99:99:3410,291,0 1/1:0,131:131:99:4537,393,0 1/1:0,144:144:99:4958,432,0 1/1:0,165:165:99:5750,496,0 1/1:4,134:138:99:4767,367,0 1/1:0,111:111:99:3814,333,0 1/1:0,136:136:99:4963,409,0 1/1:0,104:104:99:3630,312,0 1/1:1,142:143:99:4933,417,0 1/1:0,100:100:99:3502,300,0 1/1:2,135:137:99:4837,406,0 1/1:0,142:142:99:4885,427,0 0/1:41,27:68:99:717,0,1226 1/1:1,81:82:99:2848,207,0 1/1:0,78:78:99:2654,235,0 1/1:0,96:96:99:3249,289,0 0/1:40,38:78:99:1024,0,1157 1/1:0,96:96:99:3310,289,0 1/1:0,112:112:99:3763,336,0 0/1:42,38:80:99:1013,0,1124 0/0:41,0:41:78:0,78,1170 0/1:64,53:117:99:1589,0,1806 0/0:59,0:59:99:0,105,1800 1/1:0,101:101:99:3375,303,0 0/1:57,61:118:99:1738,0,1581 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 1/1:0,149:149:99:5223,447,0 1/1:0,125:125:99:4352,376,0 1/1:0,162:162:99:5453,486,0 0/1:85,70:155:99:1971,0,2400 1/1:0,192:192:99:6860,577,0 1/1:0,186:186:99:6522,557,0 1/1:0,103:103:99:3333,308,0 0/1:63,61:124:99:1599,0,1726 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:84:0,84,1260 1/1:0,143:143:99:4791,429,0 0/1:57,53:110:99:1448,0,1690 1/1:0,106:106:99:3575,317,0 0/1:60,48:108:99:1316,0,1747 0/1:63,73:136:99:2055,0,1819 0/1:69,72:141:99:2086,0,2087 0/1:75,72:147:99:2049,0,2209 0/1:70,68:138:99:1936,0,2049 0/0:55,0:55:99:0,120,1800 0/1:79,68:147:99:2076,0,2437 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 1/1:0,118:118:99:3958,355,0 0/1:75,51:126:99:1330,0,2198 0/1:38,33:71:99:1013,0,1092 0/1:68,62:130:99:1796,0,1976 1/1:1,96:97:99:3222,257,0 0/1:101,72:173:99:2039,0,3112 0/1:97,84:181:99:2428,0,2934 0/0:55,0:55:99:0,120,1800 1/1:0,146:146:99:5374,439,0 0/1:57,72:129:99:2110,0,1545 0/1:57,58:115:99:1682,0,1697 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/1:67,66:133:99:1908,0,1953 0/1:48,40:88:99:1157,0,1503 1/1:0,56:56:99:2074,168,0 0/0:29,0:29:69:0,69,1035 0/1:89,81:170:99:2478,0,2597 1/1:0,77:77:99:2606,230,0 1/1:3,131:134:99:4570,384,0 0/1:58,53:111:99:1580,0,1696 0/1:78,72:150:99:2126,0,2032 0/0:28,0:28:60:0,60,900 0/1:61,57:118:99:1661,0,1784 0/0:31,0:31:69:0,69,1035 0/1:73,62:135:99:1878,0,2076 0/1:56,49:105:99:1499,0,1698 0/1:47,49:96:99:1551,0,1365 0/1:35,47:82:99:1327,0,963 0/1:28,31:59:99:845,0,830 0/1:43,27:70:99:791,0,1294 0/0:28,0:28:60:0,60,900 1/1:1,109:110:99:3892,292,0 1/1:1,90:91:99:3276,237,0 1/1:0,160:160:99:5692,480,0 1/1:0,129:129:99:4103,387,0 1/1:0,126:126:99:3954,378,0 1/1:0,80:80:99:2802,241,0 0/1:91,105:196:99:3191,0,2688 1/1:0,182:182:99:5657,545,0 1/1:1,118:119:99:3919,319,0 0/1:64,50:114:99:1573,0,1876 1/1:0,70:70:99:2513,210,0 1/1:0,129:129:99:4316,388,0 1/1:0,103:103:99:3272,309,0 1/1:0,65:65:99:2391,195,0 1/1:0,92:92:99:3438,277,0 1/1:0,85:85:99:2929,255,0 1/1:0,106:106:99:3894,318,0 +20 16359650 rs8116503 C T 617575.00 PASS HWP=0.3656;AC=30;culprit=FS;MQ0=0;ReadPosRankSum=0.209;AN=200;InbreedingCoeff=0.0337;AF=0.19;GQ_STDDEV=851.91;FS=0.0;DP=60940;GQ_MEAN=599.24;POSITIVE_TRAIN_SITE;VQSLOD=7.02;ClippingRankSum=0.002;BaseQRankSum=-5.258;MLEAF=0.19;MLEAC=331;MQ=59.68;QD=16.34;DB;MQRankSum=0.268;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:33,0:33:70:0,70,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/1:81,65:146:99:1949,0,2689 0/0:33,0:33:75:0,75,1188 0/0:27,0:27:69:0,69,1035 0/1:71,55:126:99:1601,0,2224 0/0:32,0:32:75:0,75,1125 0/0:37,0:37:90:0,90,1350 0/1:61,60:121:99:1796,0,1925 0/0:60,0:60:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/1:56,61:117:99:1787,0,1745 0/0:41,0:41:78:0,78,1170 0/1:85,65:150:99:1924,0,2884 0/0:59,0:59:99:0,105,1800 0/0:27,0:27:60:0,60,900 0/1:54,56:110:99:1730,0,1766 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 0/0:52,0:52:99:0,117,1755 0/0:46,0:46:99:0,114,1710 0/0:31,0:31:66:0,66,990 0/1:94,89:183:99:2700,0,3126 0/0:95,0:95:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:81:0,81,1215 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:84:0,84,1260 0/1:70,75:145:99:2244,0,2230 0/0:32,0:32:63:0,63,945 0/1:46,63:109:99:1949,0,1448 0/1:68,65:133:99:1937,0,2225 0/1:61,71:132:99:2243,0,1876 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:77,61:138:99:1812,0,2594 0/0:55,0:55:99:0,120,1800 0/1:87,74:161:99:2278,0,3066 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:53,64:117:99:1985,0,1666 0/1:75,56:131:99:1604,0,2506 0/1:53,56:109:99:1621,0,1914 0/1:72,67:139:99:1953,0,2575 0/1:72,67:139:99:1852,0,2281 0/0:44,0:44:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 1/1:0,173:173:99:6545,521,0 0/1:51,73:124:99:2297,0,1621 0/0:34,0:34:78:0,78,1170 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/1:78,65:143:99:1838,0,2587 0/0:37,0:37:90:0,90,1350 0/0:28,0:28:66:0,66,990 0/0:29,0:29:69:0,69,1035 0/0:68,0:68:99:0,120,1800 0/1:44,55:99:99:1659,0,1484 0/1:90,88:178:99:2634,0,3066 0/0:29,0:29:66:0,66,990 0/1:101,90:191:99:2646,0,3220 0/0:28,0:28:60:0,60,900 0/1:63,81:144:99:2441,0,2223 0/0:31,0:31:69:0,69,1035 0/1:58,65:123:99:1886,0,2087 0/1:57,80:137:99:2430,0,1960 0/0:30,0:30:77:0,77,1170 0/0:56,0:56:99:0,120,1800 0/1:35,42:77:99:1235,0,1224 0/1:41,40:81:99:1239,0,1490 0/0:28,0:28:60:0,60,900 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:40,0:40:90:0,90,1350 0/0:35,0:35:71:0,71,1080 0/0:31,0:31:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:67,0:67:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/0:40,0:40:99:0,99,1485 0/0:31,0:31:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:99:0,99,1485 +20 16360177 rs2236144 G T 87406.90 PASS HWP=0.0255;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.391;AN=200;InbreedingCoeff=0.1017;AF=0.041;GQ_STDDEV=309.33;FS=0.0;DP=37519;GQ_MEAN=160.44;POSITIVE_TRAIN_SITE;VQSLOD=7.37;ClippingRankSum=0.367;BaseQRankSum=-1.53;MLEAF=0.041;MLEAC=72;MQ=59.74;QD=15.56;DB;MQRankSum=0.457;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:33,0:33:70:0,70,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:45,0:45:98:0,98,1530 0/0:33,0:33:75:0,75,1188 0/0:27,0:27:69:0,69,1035 0/0:42,0:42:99:0,105,1575 0/0:32,0:32:75:0,75,1125 0/0:37,0:37:90:0,90,1350 0/0:30,0:30:60:0,60,900 0/0:60,0:60:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/0:32,0:32:72:0,72,1080 0/0:41,0:41:78:0,78,1170 0/0:69,0:69:99:0,120,1800 0/0:59,0:59:99:0,105,1800 0/0:27,0:27:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 0/0:52,0:52:99:0,117,1755 0/0:46,0:46:99:0,114,1710 0/0:31,0:31:66:0,66,990 0/0:79,0:79:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:81:0,81,1215 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/0:32,0:32:63:0,63,945 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,111,1665 0/0:32,0:32:69:0,69,1035 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:47,0:47:99:0,99,1485 0/0:55,0:55:99:0,120,1800 0/0:44,0:44:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:25,0:25:66:0,66,990 0/0:38,0:38:99:0,99,1421 0/0:30,0:30:78:0,78,1170 0/0:44,0:44:99:0,102,1530 0/0:40,0:40:93:0,93,1395 0/0:44,0:44:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:34,0:34:78:0,78,1170 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:91,0:91:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:28,0:28:66:0,66,990 0/0:29,0:29:69:0,69,1035 0/0:68,0:68:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:38,0:38:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/1:56,76:132:99:2297,0,1858 0/0:28,0:28:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/1:44,36:80:99:1145,0,1487 0/0:33,0:33:87:0,87,1305 0/0:30,0:30:77:0,77,1170 0/0:56,0:56:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:40,0:40:90:0,90,1350 0/0:35,0:35:71:0,71,1080 0/0:31,0:31:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:67,0:67:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/0:40,0:40:99:0,99,1485 0/0:31,0:31:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:99:0,99,1485 +20 16360219 rs2236145 C T 78437.90 PASS HWP=0.0255;AC=2;culprit=QD;MQ0=0;ReadPosRankSum=0.328;AN=200;InbreedingCoeff=0.1017;AF=0.041;GQ_STDDEV=259.36;FS=2.5;DP=36761;GQ_MEAN=149.61;POSITIVE_TRAIN_SITE;VQSLOD=5.45;ClippingRankSum=0.621;BaseQRankSum=1.35;MLEAF=0.041;MLEAC=72;MQ=59.76;QD=15.81;DB;MQRankSum=0.213;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:33,0:33:70:0,70,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:45,0:45:98:0,98,1530 0/0:33,0:33:75:0,75,1188 0/0:27,0:27:69:0,69,1035 0/0:42,0:42:99:0,105,1575 0/0:32,0:32:75:0,75,1125 0/0:37,0:37:90:0,90,1350 0/0:30,0:30:60:0,60,900 0/0:60,0:60:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/0:32,0:32:72:0,72,1080 0/0:41,0:41:78:0,78,1170 0/0:69,0:69:99:0,120,1800 0/0:59,0:59:99:0,105,1800 0/0:27,0:27:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 0/0:52,0:52:99:0,117,1755 0/0:46,0:46:99:0,114,1710 0/0:31,0:31:66:0,66,990 0/0:79,0:79:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:81:0,81,1215 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/0:32,0:32:63:0,63,945 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,111,1665 0/0:32,0:32:69:0,69,1035 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:47,0:47:99:0,99,1485 0/0:55,0:55:99:0,120,1800 0/0:44,0:44:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:25,0:25:66:0,66,990 0/0:38,0:38:99:0,99,1421 0/0:30,0:30:78:0,78,1170 0/0:44,0:44:99:0,102,1530 0/0:40,0:40:93:0,93,1395 0/0:44,0:44:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:34,0:34:78:0,78,1170 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:91,0:91:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:28,0:28:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:68,0:68:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:38,0:38:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/1:43,55:98:99:1608,0,1265 0/0:28,0:28:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/1:31,29:60:99:927,0,898 0/0:33,0:33:87:0,87,1305 0/0:30,0:30:77:0,77,1170 0/0:56,0:56:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:40,0:40:90:0,90,1350 0/0:35,0:35:71:0,71,1080 0/0:31,0:31:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:67,0:67:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/0:40,0:40:99:0,99,1485 0/0:31,0:31:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:99:0,99,1485 +20 16360338 rs187121842 C T 1706.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=-0.848;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=61.24;FS=8.101;DP=34324;GQ_MEAN=85.46;POSITIVE_TRAIN_SITE;VQSLOD=2.35;ClippingRankSum=0.745;BaseQRankSum=-3.48;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=13.99;DB;MQRankSum=-0.684;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:33,0:33:70:0,70,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:45,0:45:98:0,98,1530 0/0:33,0:33:75:0,75,1188 0/0:27,0:27:69:0,69,1035 0/0:42,0:42:99:0,105,1575 0/0:32,0:32:75:0,75,1125 0/0:37,0:37:90:0,90,1350 0/0:30,0:30:60:0,60,900 0/0:60,0:60:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/0:32,0:32:72:0,72,1080 0/0:41,0:41:78:0,78,1170 0/0:69,0:69:99:0,120,1800 0/0:59,0:59:99:0,105,1800 0/0:27,0:27:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 0/0:52,0:52:99:0,117,1755 0/0:46,0:46:99:0,114,1710 0/0:31,0:31:66:0,66,990 0/0:79,0:79:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:81:0,81,1215 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/0:32,0:32:63:0,63,945 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,111,1665 0/0:32,0:32:69:0,69,1035 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:47,0:47:99:0,99,1485 0/0:55,0:55:99:0,120,1800 0/0:44,0:44:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:25,0:25:66:0,66,990 0/0:38,0:38:99:0,99,1421 0/0:30,0:30:78:0,78,1170 0/0:44,0:44:99:0,102,1530 0/0:40,0:40:93:0,93,1395 0/0:44,0:44:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:34,0:34:78:0,78,1170 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:91,0:91:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:28,0:28:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:68,0:68:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:38,0:38:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:54,0:54:99:0,114,1710 0/0:28,0:28:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:32,0:32:69:0,69,1151 0/0:33,0:33:87:0,87,1305 0/0:30,0:30:77:0,77,1170 0/1:62,60:122:99:1757,0,1926 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:40,0:40:90:0,90,1350 0/0:35,0:35:71:0,71,1080 0/0:31,0:31:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:67,0:67:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/0:40,0:40:99:0,99,1485 0/0:31,0:31:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:99:0,99,1485 +20 16360515 rs149204565 C T 10861.90 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.928;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=167.58;FS=0.0;DP=34605;GQ_MEAN=95.47;POSITIVE_TRAIN_SITE;VQSLOD=5.36;ClippingRankSum=-1.202;BaseQRankSum=0.671;MLEAF=0.002874;MLEAC=5;MQ=59.82;QD=13.02;DB;MQRankSum=-0.312;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:33,0:33:70:0,70,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:45,0:45:98:0,98,1530 0/0:33,0:33:75:0,75,1188 0/0:27,0:27:69:0,69,1035 0/0:42,0:42:99:0,105,1575 0/0:32,0:32:75:0,75,1125 0/0:37,0:37:90:0,90,1350 0/0:30,0:30:60:0,60,900 0/0:60,0:60:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/0:32,0:32:72:0,72,1080 0/0:41,0:41:78:0,78,1170 0/0:69,0:69:99:0,120,1800 0/0:59,0:59:99:0,105,1800 0/0:27,0:27:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 0/0:52,0:52:99:0,117,1755 0/0:46,0:46:99:0,114,1710 0/0:31,0:31:66:0,66,990 0/0:79,0:79:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:81:0,81,1215 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/0:32,0:32:63:0,63,945 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,111,1665 0/0:32,0:32:69:0,69,1035 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:47,0:47:99:0,99,1485 0/0:55,0:55:99:0,120,1800 0/0:44,0:44:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:25,0:25:66:0,66,990 0/0:38,0:38:99:0,99,1421 0/0:30,0:30:78:0,78,1170 0/0:44,0:44:99:0,102,1530 0/0:40,0:40:93:0,93,1395 0/0:44,0:44:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:34,0:34:78:0,78,1170 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:91,0:91:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:28,0:28:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:68,0:68:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:38,0:38:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:54,0:54:99:0,114,1710 0/0:28,0:28:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:32,0:32:69:0,69,1151 0/0:33,0:33:87:0,87,1305 0/0:30,0:30:77:0,77,1170 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:40,0:40:90:0,90,1350 0/0:35,0:35:71:0,71,1080 0/0:31,0:31:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:67,0:67:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/1:69,55:124:99:1584,0,2217 0/0:31,0:31:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:99:0,99,1485 +20 16360654 rs112875458 T C 5502.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.176;AN=200;InbreedingCoeff=-0.0017;AF=0.001724;GQ_STDDEV=113.74;FS=1.75;DP=34203;GQ_MEAN=89.33;POSITIVE_TRAIN_SITE;VQSLOD=4.59;ClippingRankSum=-0.618;BaseQRankSum=-0.232;MLEAF=0.001724;MLEAC=3;MQ=59.7;QD=12.31;DB;MQRankSum=0.228;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:33,0:33:70:0,70,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:45,0:45:98:0,98,1530 0/0:33,0:33:75:0,75,1188 0/0:27,0:27:69:0,69,1035 0/0:42,0:42:99:0,105,1575 0/0:32,0:32:75:0,75,1125 0/0:37,0:37:90:0,90,1350 0/0:30,0:30:60:0,60,900 0/0:60,0:60:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/0:32,0:32:72:0,72,1080 0/0:41,0:41:78:0,78,1170 0/0:69,0:69:99:0,120,1800 0/0:59,0:59:99:0,105,1800 0/0:27,0:27:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 0/0:52,0:52:99:0,117,1755 0/0:46,0:46:99:0,114,1710 0/0:31,0:31:66:0,66,990 0/0:79,0:79:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:72:0,72,1080 0/0:32,0:32:81:0,81,1215 0/0:29,0:29:69:0,69,1035 0/0:35,0:35:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/0:32,0:32:63:0,63,945 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,111,1665 0/0:32,0:32:69:0,69,1035 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:47,0:47:99:0,99,1485 0/0:55,0:55:99:0,120,1800 0/0:44,0:44:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:25,0:25:66:0,66,990 0/0:38,0:38:99:0,99,1421 0/0:30,0:30:78:0,78,1170 0/0:44,0:44:99:0,102,1530 0/0:40,0:40:93:0,93,1395 0/0:44,0:44:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:34,0:34:78:0,78,1170 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/1:81,72:153:99:2086,0,2340 0/0:37,0:37:90:0,90,1350 0/0:28,0:28:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:68,0:68:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:38,0:38:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:54,0:54:99:0,114,1710 0/0:28,0:28:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:32,0:32:69:0,69,1151 0/0:33,0:33:87:0,87,1305 0/0:30,0:30:77:0,77,1170 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:40,0:40:90:0,90,1350 0/0:35,0:35:71:0,71,1080 0/0:31,0:31:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:67,0:67:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:33,0:33:78:0,78,1170 0/0:32,0:32:72:0,72,1080 0/0:31,0:31:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:99:0,99,1485 +20 16360860 rs41276370 C T 37055.90 PASS HWP=0.0227;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.43;AN=200;InbreedingCoeff=0.1;AF=0.041;GQ_STDDEV=124.16;FS=0.0;DP=31580;GQ_MEAN=104.14;POSITIVE_TRAIN_SITE;VQSLOD=6.71;ClippingRankSum=-0.028;BaseQRankSum=-2.442;MLEAF=0.041;MLEAC=71;MQ=60.0;QD=15.99;DB;MQRankSum=0.364;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 0/0:38,0:38:90:0,90,1350 0/0:33,0:33:70:0,70,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:36,0:36:84:0,84,1260 0/0:26,0:26:57:0,57,855 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:19,0:19:51:0,51,765 0/0:45,0:45:98:0,98,1530 0/0:33,0:33:75:0,75,1188 0/0:27,0:27:69:0,69,1035 0/0:42,0:42:99:0,105,1575 0/0:28,0:28:60:0,60,900 0/0:37,0:37:90:0,90,1350 0/0:28,0:28:57:0,57,855 0/0:60,0:60:99:0,120,1800 0/0:35,0:35:78:0,78,1170 0/0:32,0:32:72:0,72,1080 0/0:41,0:41:78:0,78,1170 0/0:69,0:69:99:0,120,1800 0/0:59,0:59:99:0,105,1800 0/0:27,0:27:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:40,0:40:90:0,90,1350 0/0:40,0:40:66:0,66,990 0/0:52,0:52:99:0,117,1755 0/0:46,0:46:99:0,114,1710 0/0:31,0:31:66:0,66,990 0/0:79,0:79:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:19,0:19:51:0,51,765 0/0:32,0:32:81:0,81,1215 0/0:27,0:27:51:0,51,765 0/0:35,0:35:84:0,84,1260 0/0:62,0:62:99:0,120,1800 0/0:23,0:23:54:0,54,810 0/0:36,0:36:87:0,87,1305 0/0:46,0:46:99:0,111,1665 0/0:32,0:32:69:0,69,1035 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:47,0:47:99:0,99,1485 0/0:55,0:55:99:0,120,1800 0/0:44,0:44:81:0,81,1215 0/0:60,0:60:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:25,0:25:66:0,66,990 0/0:38,0:38:99:0,99,1421 0/0:30,0:30:78:0,78,1170 0/0:44,0:44:99:0,102,1530 0/0:40,0:40:93:0,93,1395 0/0:44,0:44:99:0,108,1620 0/0:62,0:62:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:38,0:38:87:0,87,1305 0/0:34,0:34:78:0,78,1170 0/0:71,0:71:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:37,0:37:69:0,69,1035 0/0:37,0:37:90:0,90,1350 0/0:16,0:16:36:0,36,540 0/0:26,0:26:54:0,54,810 0/0:68,0:68:99:0,120,1800 0/0:25,0:25:48:0,48,720 0/0:38,0:38:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/1:32,23:55:99:678,0,1003 0/0:28,0:28:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:24,0:24:51:0,51,765 0/1:15,14:29:99:471,0,508 0/0:33,0:33:87:0,87,1305 0/0:30,0:30:77:0,77,1170 0/0:26,0:26:63:0,63,945 0/0:14,0:14:36:0,36,540 0/0:22,0:22:57:0,57,855 0/0:23,0:23:54:0,54,810 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:75:0,75,1125 0/0:40,0:40:90:0,90,1350 0/0:20,0:20:36:0,36,540 0/0:20,0:20:43:0,43,765 0/0:27,0:27:66:0,66,990 0/0:67,0:67:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:14,0:14:27:0,27,405 0/0:28,0:28:54:0,54,810 0/0:23,0:23:60:0,60,900 0/0:24,0:24:42:0,42,630 0/0:23,0:23:54:0,54,810 0/0:18,0:18:48:0,48,676 0/0:24,0:24:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:43,0:43:99:0,99,1485 +20 16385455 rs189635871 C T 498.70 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.705;AN=200;InbreedingCoeff=-9.0E-4;AF=5.747E-4;GQ_STDDEV=18.07;FS=1.554;DP=19338;GQ_MEAN=57.51;VQSLOD=3.11;ClippingRankSum=-0.56;BaseQRankSum=-1.898;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=15.11;DB;MQRankSum=1.68;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,734 0/0:21,0:21:60:0,60,776 0/0:25,0:25:66:0,66,908 0/0:23,0:23:63:0,63,801 0/0:22,0:22:60:0,60,873 0/0:22,0:22:66:0,66,798 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,787 0/0:22,0:22:62:0,62,814 0/0:21,0:21:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:22,0:22:60:0,60,791 0/0:12,0:12:33:0,33,495 0/0:22,0:22:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,771 0/0:22,0:22:60:0,60,829 0/0:27,0:27:60:0,60,900 0/0:30,0:30:63:0,63,1113 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,884 0/0:30,0:30:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:22,0:22:60:0,60,844 0/0:15,0:15:39:0,39,585 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:23,0:23:63:0,63,925 0/0:20,0:20:60:0,60,733 0/0:31,0:31:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:63:0,63,740 0/0:24,0:24:66:0,66,858 0/0:20,0:20:60:0,60,762 0/0:23,0:23:27:0,27,750 0/0:28,0:28:66:0,66,990 0/0:22,0:22:60:0,60,812 0/0:10,0:10:24:0,24,360 0/0:22,0:22:60:0,60,820 0/0:22,0:22:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,805 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,782 0/0:20,0:20:60:0,60,732 0/0:29,0:29:66:0,66,990 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,671 0/0:22,0:22:60:0,60,900 0/0:23,0:23:63:0,63,861 0/0:21,0:21:60:0,60,825 0/0:21,0:21:60:0,60,730 0/0:27,0:27:65:0,65,1026 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,704 0/0:28,0:28:63:0,63,945 0/0:13,0:13:33:0,33,495 0/0:20,0:20:60:0,60,687 0/0:28,0:28:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,751 0/0:21,0:21:60:0,60,779 0/0:10,0:10:30:0,30,389 0/0:27,0:27:60:0,60,900 0/0:15,0:15:36:0,36,540 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,790 0/0:11,0:11:33:0,33,381 0/0:7,0:7:21:0,21,250 0/0:11,0:11:30:0,30,430 0/0:21,0:21:60:0,60,891 0/0:7,0:7:21:0,21,255 0/0:8,0:8:21:0,21,287 0/0:23,0:23:60:0,60,900 0/0:7,0:7:21:0,21,270 0/0:8,0:8:21:0,21,315 0/0:9,0:9:27:0,27,348 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:15,18:33:99:549,0,447 0/0:24,0:24:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:11,0:11:30:0,30,422 0/0:12,0:12:20:0,20,405 0/0:34,0:34:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:8,0:8:21:0,21,267 0/0:8,0:8:24:0,24,289 0/0:7,0:7:21:0,21,271 0/0:19,0:19:51:0,51,765 +20 16386981 rs16997573 G A 173109.00 PASS HWP=0.2045;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.801;AN=200;InbreedingCoeff=0.0566;AF=0.046;GQ_STDDEV=577.48;FS=0.0;DP=56513;GQ_MEAN=258.23;POSITIVE_TRAIN_SITE;VQSLOD=6.65;ClippingRankSum=-0.253;BaseQRankSum=2.95;MLEAF=0.046;MLEAC=80;MQ=59.6;QD=14.43;DB;MQRankSum=0.24;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:52,0:52:99:0,120,1800 0/0:46,0:46:96:0,96,1440 0/0:37,0:37:75:0,75,1312 0/0:50,0:50:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,111,1665 0/0:43,0:43:99:0,108,1665 0/0:62,0:62:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:45,0:45:84:0,84,1260 0/0:31,0:31:72:0,72,1080 0/0:53,0:53:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:36,0:36:73:0,73,1208 0/0:40,0:40:88:0,88,1467 0/0:34,0:34:87:0,87,1305 0/0:41,0:41:86:0,86,1305 0/0:38,0:38:87:0,87,1305 0/1:64,66:130:99:1928,0,1767 0/0:34,0:34:87:0,87,1305 0/0:43,0:43:99:0,99,1485 0/0:39,0:39:99:0,102,1408 0/0:84,0:84:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/1:89,85:174:99:2293,0,2433 0/0:116,0:116:99:0,120,1800 0/0:116,0:116:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:62,0:62:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:98,0:98:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:48,0:48:99:0,102,1530 0/0:85,0:85:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:139,0:139:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:45,0:45:99:0,102,1530 0/0:34,0:34:69:0,69,1035 0/0:43,0:43:99:0,102,1530 0/0:97,0:97:99:0,120,1800 0/0:43,0:43:99:0,99,1485 0/0:77,0:77:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:68,0:68:99:0,120,1800 0/0:50,0:50:99:0,117,1755 0/0:50,0:50:99:0,105,1575 0/0:44,0:44:99:0,102,1530 0/0:50,0:50:99:0,120,1800 0/0:47,0:47:99:0,108,1620 0/0:26,0:26:63:0,63,945 0/0:47,0:47:99:0,120,1800 0/0:46,0:46:99:0,114,1710 0/0:70,0:70:99:0,120,1800 0/0:48,0:48:99:0,108,1620 0/0:75,0:75:99:0,120,1800 0/0:29,0:29:60:0,60,900 0/0:36,0:36:63:0,63,945 0/0:36,0:36:84:0,84,1260 0/0:112,0:112:99:0,120,1800 0/0:29,0:29:60:0,60,900 0/0:36,0:36:85:0,85,1350 0/0:50,0:50:99:0,112,1710 0/0:47,0:47:99:0,120,1800 0/0:29,0:29:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:37,0:37:86:0,86,1350 0/0:42,0:42:99:0,105,1575 0/0:40,0:40:99:0,102,1530 0/0:54,0:54:99:0,120,1800 +20 16407698 rs6111110 T A 141435.00 PASS HWP=0.8015;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.34;AN=200;InbreedingCoeff=-0.0333;AF=0.032;GQ_STDDEV=628.65;FS=1.174;DP=49323;GQ_MEAN=239.0;POSITIVE_TRAIN_SITE;VQSLOD=3.69;ClippingRankSum=-0.74;BaseQRankSum=-1.402;MLEAF=0.032;MLEAC=56;MQ=59.68;QD=12.44;DB;MQRankSum=0.401;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:34,0:34:87:0,87,1305 0/0:32,0:32:90:0,90,1350 0/0:32,0:32:63:0,63,1080 0/0:34,0:34:81:0,81,1215 0/0:46,0:46:99:0,120,1800 0/0:45,0:45:99:0,111,1665 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:75:0,75,1125 0/0:36,0:36:84:0,84,1260 0/0:32,0:32:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:35,0:35:99:0,99,1485 0/0:46,0:46:99:0,105,1575 0/0:29,0:29:63:0,63,945 0/0:52,0:52:99:0,120,1800 0/0:41,0:41:96:0,96,1440 0/1:81,73:154:99:2080,0,2204 0/0:45,0:45:99:0,108,1620 0/0:33,0:33:87:0,87,1305 0/0:47,0:47:99:0,111,1665 0/0:34,0:34:60:0,60,900 0/0:32,0:32:78:0,78,1170 0/0:44,0:44:96:0,96,1440 0/0:29,0:29:63:0,63,945 0/0:33,0:33:60:0,60,900 0/0:43,0:43:99:0,114,1710 0/0:44,0:44:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:30,0:30:72:0,72,1080 0/0:31,0:31:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:32,0:32:78:0,78,1170 0/0:72,0:72:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/1:104,94:198:99:2311,0,2676 0/0:32,0:32:75:0,75,1125 0/0:35,0:35:84:0,84,1260 0/0:43,0:43:99:0,108,1620 0/0:59,0:59:99:0,120,1800 0/0:42,0:42:99:0,108,1620 0/0:50,0:50:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:52,0:52:99:0,111,1665 0/0:46,0:46:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:52,0:52:99:0,111,1665 0/0:41,0:41:90:0,90,1350 0/0:54,0:54:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:34,0:34:87:0,87,1305 0/0:45,0:45:99:0,111,1665 0/0:63,0:63:99:0,120,1800 0/0:50,0:50:99:0,111,1665 0/0:76,0:76:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:43,0:43:96:0,96,1440 0/0:45,0:45:99:0,105,1575 0/0:33,0:33:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:50,0:50:99:0,120,1800 0/0:36,0:36:72:0,72,1080 0/0:58,0:58:99:0,120,1800 0/0:46,0:46:99:0,111,1665 0/0:71,0:71:99:0,120,1800 0/0:35,0:35:87:0,87,1305 0/0:29,0:29:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:43,0:43:90:0,90,1350 0/0:36,0:36:84:0,84,1260 0/0:29,0:29:66:0,66,990 0/0:38,0:38:84:0,84,1440 0/0:28,0:28:66:0,66,990 0/0:37,0:37:87:0,87,1305 0/0:25,0:25:66:0,66,990 0/0:41,0:41:96:0,96,1440 0/0:31,0:31:78:0,78,1170 0/0:54,0:54:99:0,120,1800 0/0:35,0:35:75:0,75,1125 0/0:27,0:27:63:0,63,945 0/0:33,0:33:84:0,84,1248 0/0:71,0:71:99:0,120,1800 0/0:40,0:40:87:0,87,1395 0/0:32,0:32:72:0,72,1080 0/0:44,0:44:99:0,111,1665 0/0:33,0:33:72:0,72,1080 0/0:35,0:35:75:0,75,1125 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:36,0:36:84:0,84,1260 0/0:32,0:32:63:0,63,945 0/0:42,0:42:90:0,90,1350 +20 16410559 rs34550969 A T 107683.00 PASS HWP=0.9607;AC=25;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.443;AN=200;InbreedingCoeff=0.0075;AF=0.072;GQ_STDDEV=284.21;FS=0.0;DP=31048;GQ_MEAN=172.05;POSITIVE_TRAIN_SITE;VQSLOD=5.93;ClippingRankSum=0.015;BaseQRankSum=0.928;MLEAF=0.072;MLEAC=126;MQ=59.68;QD=14.78;DB;MQRankSum=0.315;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:40,0:40:99:0,111,1632 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,753 0/0:32,0:32:84:0,84,1260 0/0:28,0:28:75:0,75,1125 0/0:44,0:44:99:0,105,1575 0/0:40,0:40:99:0,102,1530 0/0:24,0:24:63:0,63,945 0/0:36,0:36:81:0,81,1215 0/0:30,0:30:87:0,87,1241 0/0:31,0:31:84:0,84,1260 0/0:29,0:29:72:0,72,1080 0/1:42,35:77:99:1030,0,1314 0/1:24,22:46:99:627,0,738 0/0:61,0:61:99:0,120,1800 0/1:47,62:109:99:1874,0,1303 0/0:53,0:53:99:0,120,1800 0/1:88,83:171:99:2346,0,2360 0/0:67,0:67:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/1:79,73:152:99:2017,0,2257 0/0:49,0:49:99:0,120,1800 0/0:20,0:20:60:0,60,644 0/0:29,0:29:77:0,77,1019 0/0:28,0:28:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,834 0/0:33,0:33:99:0,99,1122 0/0:35,0:35:81:0,81,1215 0/0:22,0:22:60:0,60,900 0/0:33,0:33:72:0,72,1080 0/1:37,37:74:99:1168,0,1105 0/0:38,0:38:93:0,93,1395 0/0:30,0:30:78:0,78,1059 0/0:25,0:25:60:0,60,900 0/0:32,0:32:74:0,74,1003 0/0:84,0:84:99:0,120,1800 0/0:32,0:32:78:0,78,1140 0/1:25,19:44:99:575,0,760 0/0:21,0:21:60:0,60,799 0/1:18,10:28:99:299,0,538 0/1:24,11:35:99:300,0,715 0/0:28,0:28:69:0,69,1035 0/0:32,0:32:81:0,81,1215 0/0:35,0:35:82:0,82,1350 0/1:14,24:38:99:781,0,414 0/0:33,0:33:87:0,87,1275 0/1:44,59:103:99:1851,0,1401 0/0:68,0:68:99:0,120,1800 0/0:28,0:28:61:0,61,956 0/1:20,18:38:99:524,0,567 0/1:15,14:29:99:451,0,429 0/1:23,23:46:99:680,0,666 0/1:34,29:63:99:926,0,1051 0/1:20,23:43:99:731,0,584 0/0:27,0:27:64:0,64,927 0/0:29,0:29:72:0,72,1080 0/0:32,0:32:87:0,87,1226 0/1:68,54:122:99:1612,0,2227 0/0:22,0:22:63:0,63,819 0/0:22,0:22:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:68,0:68:99:0,120,1800 0/1:8,18:26:99:551,0,237 0/0:26,0:26:60:0,60,900 0/0:46,0:46:99:0,120,1800 0/1:16,23:39:99:753,0,465 0/0:24,0:24:69:0,69,1035 0/0:25,0:25:63:0,63,945 0/0:28,0:28:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/1:30,18:48:99:528,0,923 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:24,11:35:99:326,0,759 0/0:23,0:23:66:0,66,990 0/0:28,0:28:76:0,76,1038 0/1:13,18:31:99:621,0,321 0/1:15,14:29:99:483,0,432 0/1:12,14:26:99:445,0,387 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,758 0/0:23,0:23:69:0,69,808 0/0:36,0:36:96:0,96,1440 0/0:25,0:25:63:0,63,945 0/0:88,0:88:99:0,120,1800 0/0:20,0:20:60:0,60,702 0/0:24,0:24:60:0,60,900 0/0:26,0:26:66:0,66,990 0/1:19,17:36:99:542,0,539 0/0:21,0:21:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:21,0:21:60:0,60,873 0/0:28,0:28:65:0,65,1043 0/0:20,0:20:60:0,60,682 0/0:29,0:29:70:0,70,1080 +20 16478344 rs74643155 G T 6441.22 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.496;AN=200;InbreedingCoeff=-0.0052;AF=0.005172;GQ_STDDEV=73.24;FS=3.43;DP=22570;GQ_MEAN=74.69;POSITIVE_TRAIN_SITE;VQSLOD=3.62;ClippingRankSum=0.047;BaseQRankSum=-2.813;MLEAF=0.005172;MLEAC=9;MQ=60.0;QD=11.2;DB;MQRankSum=0.193;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,818 0/0:21,0:21:60:0,60,836 0/0:21,0:21:60:0,60,801 0/0:26,0:26:64:0,64,973 0/0:34,0:34:87:0,87,1305 0/0:28,0:28:75:0,75,1125 0/0:30,0:30:66:0,66,990 0/0:27,0:27:69:0,69,1035 0/0:32,0:32:75:0,75,1125 0/0:21,0:21:63:0,63,792 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:30,0:30:75:0,75,1125 0/0:26,0:26:69:0,69,1035 0/1:26,14:40:99:377,0,802 0/0:34,0:34:84:0,84,1260 0/0:28,0:28:69:0,69,1035 0/0:36,0:36:96:0,96,1440 0/0:29,0:29:81:0,81,1215 0/0:24,0:24:63:0,63,913 0/0:42,0:42:99:0,111,1665 0/0:42,0:42:99:0,105,1575 0/0:26,0:26:72:0,72,999 0/0:30,0:30:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:69:0,69,960 0/0:40,0:40:99:0,108,1606 0/0:25,0:25:66:0,66,990 0/0:26,0:26:66:0,66,921 0/0:33,0:33:90:0,90,1350 0/0:29,0:29:78:0,78,1170 0/0:30,0:30:84:0,84,1112 0/0:30,0:30:72:0,72,1024 0/0:21,0:21:60:0,60,768 0/1:37,28:65:99:691,0,1136 0/0:34,0:34:99:0,99,1485 0/0:21,0:21:60:0,60,900 0/0:31,0:31:75:0,75,1086 0/0:16,0:16:42:0,42,593 0/0:21,0:21:60:0,60,721 0/0:24,0:24:60:0,60,851 0/0:21,0:21:60:0,60,881 0/0:26,0:26:67:0,67,941 0/0:28,0:28:71:0,71,986 0/0:21,0:21:60:0,60,900 0/0:28,0:28:81:0,81,998 0/0:42,0:42:99:0,120,1800 0/0:43,0:43:96:0,96,1440 0/0:22,0:22:63:0,63,814 0/0:30,0:30:20:0,20,1038 0/0:21,0:21:60:0,60,770 0/0:20,0:20:60:0,60,701 0/0:24,0:24:60:0,60,900 0/0:22,0:22:62:0,62,900 0/0:30,0:30:62:0,62,1197 0/0:22,0:22:60:0,60,900 0/0:30,0:30:75:0,75,1125 0/0:38,0:38:97:0,97,1485 0/0:24,0:24:62:0,62,903 0/0:24,0:24:60:0,60,900 0/0:25,0:25:72:0,72,1080 0/0:28,0:28:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:27,0:27:78:0,78,1170 0/0:26,0:26:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:35,0:35:96:0,96,1440 0/0:25,0:25:60:0,60,900 0/0:33,0:33:90:0,90,1350 0/0:21,0:21:60:0,60,782 0/0:36,0:36:81:0,81,1215 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,867 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,890 0/0:28,0:28:60:0,60,900 0/0:22,0:22:63:0,63,799 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:31,0:31:78:0,78,1170 0/0:21,0:21:63:0,63,773 0/0:23,0:23:60:0,60,900 0/0:38,0:38:99:0,108,1620 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:24,0:24:66:0,66,936 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,721 0/0:30,0:30:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:63:0,63,725 diff --git a/hail/python/hail/docs/data/samplepart3.vcf b/hail/python/hail/docs/data/samplepart3.vcf new file mode 100644 index 00000000000..05408e5a78d --- /dev/null +++ b/hail/python/hail/docs/data/samplepart3.vcf @@ -0,0 +1,172 @@ +##fileformat=VCFv4.2 +##fileDate=2016-01-28 +##source=Hailv0.0 +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FORMAT= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##FILTER= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +##INFO= +#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT C1046::HG02024 C1046::HG02025 C1046::HG02026 C1047::HG00731 C1047::HG00732 C1047::HG00733 C1048::HG02024 C1048::HG02025 C1048::HG02026 C1049::HG00731 C1049::HG00732 C1049::HG00733 C1050::HG03006 C1051::HG03642 C1589::HG02922 C1589::HG03006 C1589::HG03052 C1589::HG03642 C1589::NA12878 C1589::NA19017 C1589::NA19625 C1589::NA19648 C1589::NA20845 C339::NA12878 C339::NA12891 C454::NA19625 C456::NA12878 C456::NA12891 C464::NA20845 C469::HG02025 C469::HG02026 C470::NA19017 C474::NA19648 C477::HG00731 C477::HG00732 C958::HG03052 C959::HG02922 HG00096 HG00100 HG00116 HG00117 HG00119 HG00120 HG00123 HG00124 HG00131 HG00133 HG00145 HG00146_A1 HG00155_A1 HG00157 HG00158 HG00159 HG00160 HG00176 HG00239 HG00242 HG00243 HG00244 HG00245_A1 HG00255 HG00258 HG00262 HG00264 HG00265 HG00268 HG00272 HG00306 HG00308 HG00311 HG00312 HG00357 HG00361 HG00366 HG00367 HG00368 HG00369 HG00371 HG00372 HG00373 HG00377 HG00379 HG00380 HG00384 HG00403 HG00404 HG00409 HG00410 HG00419 HG00551 HG00598 HG00599 HG00610 HG00611 HG00622 HG00623 HG00625 HG00626 HG00628 HG00629 +20 16486698 rs2295115 G A 760860.00 PASS HWP=0.0284;AC=55;culprit=FS;MQ0=0;ReadPosRankSum=0.805;AN=200;InbreedingCoeff=0.0779;AF=0.234;GQ_STDDEV=785.2;FS=0.0;DP=63681;GQ_MEAN=595.06;POSITIVE_TRAIN_SITE;VQSLOD=5.42;ClippingRankSum=-0.54;BaseQRankSum=3.15;MLEAF=0.234;MLEAC=408;MQ=59.74;QD=18.03;DB;MQRankSum=0.153;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:59,61:120:99:1739,0,1738 0/0:35,0:35:84:0,84,1260 0/1:48,51:99:99:1579,0,1294 0/0:36,0:36:90:0,90,1329 0/1:64,45:109:99:1283,0,1814 0/0:35,0:35:77:0,77,1296 0/1:51,51:102:99:1619,0,1524 0/0:33,0:33:81:0,81,1215 0/1:56,73:129:99:2086,0,1659 0/0:30,0:30:75:0,75,1125 0/1:52,52:104:99:1643,0,1426 0/0:21,0:21:60:0,60,900 0/1:60,49:109:99:1399,0,1664 0/1:61,47:108:99:1414,0,1701 0/0:40,0:40:88:0,88,1430 0/1:39,50:89:99:1480,0,1110 0/0:28,0:28:72:0,72,1080 0/1:42,54:96:99:1615,0,1098 0/0:27,0:27:66:0,66,990 0/0:39,0:39:93:0,93,1395 0/0:25,0:25:69:0,69,930 0/1:48,52:100:99:1642,0,1297 0/0:35,0:35:90:0,90,1350 0/0:40,0:40:78:0,78,1170 0/0:45,0:45:93:0,93,1395 0/0:54,0:54:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:46,0:46:99:0,105,1575 0/0:56,0:56:99:0,120,1800 0/1:45,63:108:99:1738,0,1175 0/0:31,0:31:78:0,78,1170 0/1:116,110:226:99:3082,0,3411 0/0:109,0:109:99:0,120,1800 0/1:118,84:202:99:2496,0,3518 0/0:29,0:29:60:0,60,900 0/0:38,0:38:60:0,60,900 0/1:48,50:98:99:1570,0,1274 0/0:56,0:56:99:0,120,1800 0/1:72,81:153:99:2436,0,1866 0/0:43,0:43:94:0,94,1641 0/1:68,56:124:99:1626,0,1750 0/1:64,56:120:99:1648,0,1750 0/0:54,0:54:99:0,114,1710 0/1:66,78:144:99:2363,0,1828 0/0:77,0:77:99:0,120,1800 0/1:71,64:135:99:1907,0,1988 0/0:76,0:76:99:0,120,1800 0/1:84,84:168:99:2591,0,2408 0/0:53,0:53:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/1:51,61:112:99:1943,0,1359 1/1:0,111:111:99:4151,334,0 0/1:40,40:80:99:1244,0,1157 0/0:48,0:48:99:0,120,1800 0/1:70,63:133:99:1793,0,1831 0/0:75,0:75:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/1:74,83:157:99:2577,0,1880 0/1:76,65:141:99:2027,0,2238 0/0:60,0:60:99:0,120,1800 0/1:63,66:129:99:2045,0,1698 0/0:95,0:95:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:32,0:32:81:0,81,1215 0/1:28,31:59:99:986,0,804 0/1:32,39:71:99:1248,0,942 0/0:75,0:75:99:0,120,1800 0/1:40,41:81:99:1241,0,1126 0/0:61,0:61:99:0,120,1800 0/0:35,0:35:84:0,84,1260 0/1:86,74:160:99:2069,0,2326 0/0:27,0:27:63:0,63,945 0/1:48,47:95:99:1419,0,1410 0/0:21,0:21:60:0,60,900 0/0:35,0:35:80:0,80,1215 1/1:0,107:107:99:3904,322,0 0/0:38,0:38:76:0,76,1530 0/0:30,0:30:78:0,78,1170 0/1:34,39:73:99:1225,0,1048 0/1:35,37:72:99:1151,0,996 0/1:30,32:62:99:1002,0,851 0/1:32,47:79:99:1490,0,956 0/1:37,46:83:99:1387,0,1080 1/1:0,127:127:99:4620,382,0 0/0:30,0:30:69:0,69,1035 0/0:22,0:22:63:0,63,811 0/1:44,42:86:99:1274,0,1214 0/0:79,0:79:99:0,120,1800 1/1:3,130:133:99:4565,336,0 0/0:32,0:32:75:0,75,1125 0/1:42,49:91:99:1514,0,1185 0/1:31,37:68:99:1117,0,901 1/1:1,97:98:99:3552,258,0 0/1:44,49:93:99:1449,0,1146 0/1:31,31:62:99:924,0,920 0/0:37,0:37:78:0,78,1170 0/1:35,33:68:99:988,0,1078 1/1:1,100:101:99:3492,267,0 +20 16492045 . T G 7137.03 VQSRTrancheSNP99.90to99.95 HWP=0.432;AC=17;culprit=FS;MQ0=0;ReadPosRankSum=-1.481;AN=200;InbreedingCoeff=-0.0852;AF=0.041;GQ_STDDEV=35.83;FS=100.986;DP=29245;GQ_MEAN=55.12;VQSLOD=-91.85;ClippingRankSum=2.02;BaseQRankSum=-4.297;MLEAF=0.048;MLEAC=83;MQ=59.48;QD=1.8;MQRankSum=0.461;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:33,0:33:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:32,0:32:61:0,61,1035 0/0:30,0:30:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:33,0:33:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:27,0:27:78:0,78,978 0/0:26,0:26:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:43,0:43:90:0,90,1471 0/0:28,0:28:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:29,0:29:69:0,69,1035 0/0:29,0:29:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:36,0:36:63:0,63,945 0/0:38,0:38:60:0,60,900 0/0:46,0:46:0:0,0,967 0/0:40,0:40:0:0,0,376 0/0:36,0:36:0:0,0,454 0/0:25,0:25:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:58,0:58:0:0,0,1234 0/0:57,0:57:0:0,0,1244 0/0:31,0:31:66:0,66,990 0/0:29,0:29:86:0,86,975 0/0:21,0:21:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:38,0:38:0:0,0,827 0/0:41,0:41:19:0,19,936 0/0:25,0:25:0:0,0,579 0/0:31,0:31:0:0,0,662 0/0:29,0:29:18:0,18,720 0/0:32,0:32:0:0,0,593 0/1:35,10:45:54:54,0,936 0/1:18,20:38:99:188,0,430 0/0:44,0:44:0:0,0,792 0/0:65,0:65:0:0,0,1350 0/0:58,0:58:0:0,0,1212 0/0:83,0:83:0:0,0,1644 0/0:32,0:32:0:0,0,670 0/1:18,13:31:67:67,0,543 0/1:12,13:25:99:110,0,313 0/1:32,17:49:23:23,0,767 0/0:28,0:28:60:0,60,900 0/0:27,0:27:0:0,0,608 0/1:29,22:51:99:153,0,743 0/0:41,0:41:0:0,0,885 0/1:23,28:51:99:308,0,519 0/0:64,0:64:0:0,0,1084 0/1:20,8:28:19:19,0,530 0/0:30,0:30:11:0,11,753 0/0:74,0:74:0:0,0,1623 0/1:17,17:34:99:101,0,408 0/0:28,0:28:26:0,26,781 0/0:34,0:34:60:0,60,900 0/0:23,0:23:13:0,13,535 0/0:23,0:23:0:0,0,496 0/1:44,34:78:99:181,0,1164 0/0:29,0:29:0:0,0,640 0/1:48,21:69:56:56,0,1306 0/0:34,0:34:5:0,5,808 0/1:52,30:82:99:108,0,1279 0/0:38,0:38:0:0,0,916 0/0:36,0:36:0:0,0,608 0/0:40,0:40:0:0,0,863 0/1:33,18:51:99:110,0,915 0/0:34,0:34:26:0,26,845 0/0:45,0:45:0:0,0,975 0/1:26,18:44:69:69,0,714 0/0:29,0:29:0:0,0,635 0/0:24,0:24:0:0,0,426 0/1:24,17:41:77:77,0,596 0/0:49,0:49:0:0,0,1163 0/1:29,23:52:99:112,0,691 0/0:61,0:61:46:0,46,1553 0/0:26,0:26:63:0,63,945 0/0:30,0:30:69:0,69,1035 0/0:29,0:29:69:0,69,1035 0/0:50,0:50:11:0,11,1134 0/0:25,0:25:60:0,60,880 0/0:28,0:28:63:0,63,945 0/0:46,0:46:0:0,0,933 0/0:23,0:23:0:0,0,515 0/0:31,0:31:63:0,63,945 0/0:22,0:22:63:0,63,759 0/0:32,0:32:0:0,0,696 0/1:18,17:35:99:109,0,479 0/0:19,0:19:13:0,13,446 0/0:30,0:30:0:0,0,643 +20 16492163 rs16997775 T C 34851.40 PASS HWP=0.7358;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.177;AN=200;InbreedingCoeff=0.0274;AF=0.023;GQ_STDDEV=144.88;FS=0.0;DP=24646;GQ_MEAN=90.26;POSITIVE_TRAIN_SITE;VQSLOD=6.02;ClippingRankSum=0.096;BaseQRankSum=4.15;MLEAF=0.023;MLEAC=40;MQ=59.7;QD=16.75;DB;MQRankSum=0.596;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:33,0:33:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:32,0:32:61:0,61,1035 0/0:30,0:30:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:33,0:33:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:27,0:27:78:0,78,978 0/0:26,0:26:60:0,60,900 0/0:30,0:30:63:0,63,945 0/1:33,32:65:99:1049,0,967 0/0:28,0:28:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:29,0:29:69:0,69,1035 0/0:29,0:29:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:36,0:36:63:0,63,945 0/0:38,0:38:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:31,0:31:66:0,66,990 0/1:16,26:42:99:799,0,402 0/0:21,0:21:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:28,0:28:66:0,66,990 0/0:28,0:28:66:0,66,990 0/0:24,0:24:60:0,60,867 0/0:34,0:34:63:0,63,945 0/0:24,0:24:60:0,60,828 0/0:26,0:26:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:66:0,66,965 0/0:25,0:25:69:0,69,967 0/0:24,0:24:66:0,66,895 0/0:28,0:28:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:24,0:24:63:0,63,944 0/0:26,0:26:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,697 0/0:26,0:26:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:29,0:29:60:0,60,900 0/0:38,0:38:78:0,78,1170 0/0:29,0:29:60:0,60,900 0/0:34,0:34:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,823 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:30,0:30:69:0,69,1035 0/0:29,0:29:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,880 0/0:28,0:28:63:0,63,945 0/0:32,0:32:72:0,72,1080 0/0:27,0:27:66:0,66,955 0/0:31,0:31:63:0,63,945 0/0:22,0:22:63:0,63,759 0/0:27,0:27:68:0,68,849 0/0:27,0:27:66:0,66,780 0/0:22,0:22:63:0,63,798 0/0:22,0:22:60:0,60,900 +20 16493533 rs6135775 T C 422117.00 PASS HWP=0.0225;AC=55;culprit=FS;MQ0=0;ReadPosRankSum=0.397;AN=200;InbreedingCoeff=0.081;AF=0.236;GQ_STDDEV=453.35;FS=0.0;DP=38177;GQ_MEAN=327.94;POSITIVE_TRAIN_SITE;VQSLOD=6.81;ClippingRankSum=0.032;BaseQRankSum=1.82;MLEAF=0.236;MLEAC=410;MQ=59.56;QD=17.51;DB;MQRankSum=0.099;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:41,30:71:99:888,0,1210 0/0:25,0:25:66:0,66,990 0/1:27,26:53:99:743,0,680 0/0:26,0:26:60:0,60,900 0/1:31,33:64:99:940,0,796 0/0:27,0:27:60:0,60,900 0/1:44,34:78:99:1039,0,1096 0/0:23,0:23:60:0,60,900 0/1:25,38:63:99:1184,0,745 0/0:25,0:25:63:0,63,945 0/1:33,36:69:99:820,0,843 0/0:21,0:21:60:0,60,799 0/1:43,42:85:99:1262,0,1151 0/1:32,38:70:99:1170,0,888 0/0:23,0:23:60:0,60,784 0/1:36,41:77:99:1082,0,956 0/0:24,0:24:60:0,60,900 0/1:43,30:73:99:799,0,1287 0/0:22,0:22:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:36,40:76:99:1091,0,907 0/0:22,0:22:60:0,60,900 0/0:36,0:36:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:74:0,74,1170 0/0:26,0:26:69:0,69,1035 0/0:33,0:33:72:0,72,1080 0/1:26,25:51:99:755,0,735 0/0:31,0:31:60:0,60,900 0/1:49,54:103:99:1515,0,1332 0/0:43,0:43:99:0,102,1530 0/1:52,50:102:99:1459,0,1350 0/0:21,0:21:60:0,60,900 0/0:24,0:24:66:0,66,875 0/1:33,28:61:99:753,0,904 0/0:25,0:25:60:0,60,900 0/1:35,29:64:99:790,0,1049 0/0:27,0:27:60:0,60,900 0/1:19,21:40:99:590,0,566 0/1:17,21:38:99:630,0,492 0/0:27,0:27:60:0,60,900 0/1:24,28:52:99:754,0,679 0/0:35,0:35:87:0,87,1305 0/1:32,28:60:99:740,0,906 0/0:28,0:28:69:0,69,1035 0/1:71,48:119:99:1417,0,2029 0/0:39,0:39:81:0,81,1305 0/0:25,0:25:63:0,63,945 0/1:26,21:47:99:591,0,775 1/1:0,34:34:99:1147,102,0 0/1:36,32:68:99:849,0,1017 0/0:26,0:26:66:0,66,990 0/1:29,27:56:99:702,0,823 0/0:33,0:33:72:0,72,1080 0/0:27,0:27:69:0,69,1035 0/1:43,33:76:99:931,0,1246 0/1:51,45:96:99:1331,0,1382 0/0:25,0:25:60:0,60,900 0/1:34,25:59:99:670,0,983 0/0:38,0:38:93:0,93,1395 0/0:24,0:24:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:34,0:34:64:0,64,1226 0/1:25,33:58:99:1061,0,682 0/1:27,15:42:99:402,0,727 0/0:48,0:48:99:0,114,1710 0/1:32,24:56:99:624,0,849 0/0:35,0:35:96:0,96,1440 0/0:23,0:23:60:0,60,900 0/1:78,42:120:99:1149,0,2002 0/0:23,0:23:60:0,60,900 0/1:31,24:55:99:610,0,819 0/0:25,0:25:61:0,61,990 0/0:24,0:24:60:0,60,900 1/1:0,53:53:99:1954,159,0 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,828 0/1:14,26:40:99:743,0,358 0/1:22,12:34:99:293,0,625 0/1:16,32:48:99:1013,0,371 0/1:26,37:63:99:1118,0,725 0/1:26,16:42:99:453,0,779 1/1:0,84:84:99:3159,251,0 0/0:21,0:21:60:0,60,839 0/0:20,0:20:60:0,60,841 0/1:38,27:65:99:703,0,1034 0/0:29,0:29:63:0,63,945 1/1:0,84:84:99:2719,251,0 0/0:22,0:22:60:0,60,900 0/1:29,32:61:99:973,0,789 0/1:21,18:39:99:510,0,649 1/1:0,85:85:99:2756,253,0 0/1:35,30:65:99:851,0,880 0/1:12,31:43:99:936,0,244 0/0:27,0:27:60:0,60,900 0/1:22,27:49:99:829,0,563 1/1:0,58:58:99:2162,174,0 +20 16493580 rs6135776 A G 279178.00 PASS HWP=0.0319;AC=55;culprit=FS;MQ0=0;ReadPosRankSum=0.341;AN=200;InbreedingCoeff=0.0768;AF=0.235;GQ_STDDEV=296.76;FS=0.0;DP=27829;GQ_MEAN=223.07;POSITIVE_TRAIN_SITE;VQSLOD=6.8;ClippingRankSum=-0.049;BaseQRankSum=0.994;MLEAF=0.235;MLEAC=409;MQ=59.73;QD=19.18;DB;MQRankSum=0.044;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:20,15:35:99:421,0,660 0/0:25,0:25:66:0,66,990 0/1:13,17:30:99:545,0,324 0/0:26,0:26:60:0,60,900 0/1:20,16:36:99:471,0,616 0/0:27,0:27:60:0,60,900 0/1:24,18:42:99:560,0,795 0/0:23,0:23:60:0,60,900 0/1:18,22:40:99:694,0,529 0/0:25,0:25:63:0,63,945 0/1:20,18:38:99:516,0,624 0/0:21,0:21:60:0,60,799 0/1:30,37:67:99:1211,0,934 0/1:25,20:45:99:606,0,792 0/0:17,0:17:42:0,42,630 0/1:27,26:53:99:753,0,833 0/0:24,0:24:60:0,60,900 0/1:27,22:49:99:663,0,782 0/0:22,0:22:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:30,23:53:99:649,0,919 0/0:22,0:22:60:0,60,900 0/0:36,0:36:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:74:0,74,1170 0/0:26,0:26:69:0,69,1035 0/0:33,0:33:72:0,72,1080 0/1:15,21:36:99:721,0,435 0/0:31,0:31:60:0,60,900 0/1:36,35:71:99:1018,0,1157 0/0:43,0:43:99:0,102,1530 0/1:32,37:69:99:1211,0,1047 0/0:21,0:21:60:0,60,900 0/0:24,0:24:66:0,66,875 0/1:20,18:38:99:476,0,681 0/0:25,0:25:60:0,60,900 0/1:21,24:45:99:751,0,682 0/0:8,0:8:21:0,21,294 0/1:11,9:20:99:301,0,337 0/1:8,13:21:99:431,0,252 0/0:25,0:25:66:0,66,990 0/1:24,21:45:99:668,0,760 0/0:35,0:35:87:0,87,1305 0/1:22,17:39:99:558,0,756 0/0:28,0:28:69:0,69,1035 0/1:26,35:61:99:1112,0,890 0/0:39,0:39:81:0,81,1305 0/0:25,0:25:63:0,63,945 0/1:24,14:38:99:402,0,795 1/1:0,24:24:72:907,72,0 0/1:18,20:38:99:664,0,603 0/0:26,0:26:66:0,66,990 0/1:22,20:42:99:620,0,658 0/0:33,0:33:72:0,72,1080 0/0:27,0:27:69:0,69,1035 0/1:31,21:52:99:653,0,1004 0/1:30,32:62:99:1102,0,1041 0/0:25,0:25:60:0,60,900 0/1:17,19:36:99:599,0,535 0/0:38,0:38:93:0,93,1395 0/0:24,0:24:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:34,0:34:64:0,64,1226 0/1:19,19:38:99:634,0,661 0/1:10,8:18:99:287,0,347 0/0:48,0:48:99:0,114,1710 0/1:15,16:31:99:555,0,487 0/0:52,0:52:34:0,34,1778 0/0:23,0:23:60:0,60,900 0/1:35,20:55:99:650,0,1109 0/0:23,0:23:60:0,60,900 0/1:22,14:36:99:485,0,726 0/0:25,0:25:61:0,61,990 0/0:24,0:24:60:0,60,900 1/1:0,37:37:99:1470,110,0 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,828 0/1:11,13:24:99:404,0,378 0/1:18,10:28:99:311,0,612 0/1:11,13:24:99:431,0,334 0/1:15,21:36:99:766,0,501 0/1:15,7:22:99:233,0,488 1/1:0,59:59:99:2300,177,0 0/0:21,0:21:60:0,60,839 0/0:20,0:20:60:0,60,841 0/1:14,10:24:99:285,0,473 0/0:29,0:29:63:0,63,945 1/1:0,44:44:99:1731,132,0 0/0:22,0:22:60:0,60,900 0/1:22,18:40:99:568,0,673 0/1:12,11:23:99:393,0,414 1/1:0,52:52:99:1814,156,0 0/1:12,20:32:99:595,0,347 0/1:8,19:27:99:683,0,238 0/0:27,0:27:60:0,60,900 0/1:10,13:23:99:440,0,329 1/1:0,36:36:99:1464,108,0 +20 16508986 rs74412819 G A 5145.06 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.413;AN=200;InbreedingCoeff=-0.0047;AF=0.004598;GQ_STDDEV=55.56;FS=3.342;DP=25174;GQ_MEAN=74.21;POSITIVE_TRAIN_SITE;VQSLOD=3.86;ClippingRankSum=0.066;BaseQRankSum=-1.87;MLEAF=0.004598;MLEAC=8;MQ=60.0;QD=14.33;DB;MQRankSum=0.676;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:66:0,66,799 0/0:27,0:27:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:35,0:35:81:0,81,1215 0/0:24,0:24:66:0,66,990 0/0:23,0:23:63:0,63,945 0/0:21,0:21:63:0,63,788 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,791 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:14,18:32:99:548,0,394 0/0:31,0:31:75:0,75,1125 0/0:31,0:31:87:0,87,1212 0/0:34,0:34:81:0,81,1215 0/0:36,0:36:96:0,96,1440 0/0:36,0:36:89:0,89,1400 0/0:32,0:32:69:0,69,1178 0/0:38,0:38:96:0,96,1440 0/0:35,0:35:87:0,87,1305 0/0:42,0:42:66:0,66,990 0/0:38,0:38:75:0,75,1125 0/0:29,0:29:66:0,66,990 0/0:37,0:37:87:0,87,1305 0/0:29,0:29:75:0,75,1125 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:66:0,66,871 0/0:22,0:22:60:0,60,900 0/0:39,0:39:99:0,101,1665 0/0:57,0:57:99:0,120,1800 0/0:50,0:50:99:0,111,1665 0/0:22,0:22:60:0,60,866 0/1:20,10:30:99:262,0,713 0/0:44,0:44:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:40,0:40:93:0,93,1395 0/0:32,0:32:80:0,80,1205 0/0:29,0:29:72:0,72,1080 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:41,0:41:99:0,102,1530 0/0:39,0:39:93:0,93,1395 0/0:55,0:55:99:0,120,1800 0/0:46,0:46:99:0,117,1800 0/0:52,0:52:99:0,120,1800 0/0:35,0:35:90:0,90,1350 0/0:30,0:30:72:0,72,1080 0/0:25,0:25:72:0,72,914 0/0:22,0:22:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:30,0:30:61:0,61,1090 0/0:29,0:29:70:0,70,1146 0/0:39,0:39:88:0,88,1485 0/0:36,0:36:78:0,78,1170 0/0:60,0:60:99:0,120,1800 0/0:32,0:32:75:0,75,1125 0/0:28,0:28:75:0,75,1125 0/0:57,0:57:99:0,120,1800 0/0:32,0:32:78:0,78,1170 0/0:26,0:26:69:0,69,1011 0/0:33,0:33:78:0,78,1170 0/0:21,0:21:60:0,60,900 0/0:14,0:14:39:0,39,585 0/0:66,0:66:99:0,120,1800 0/0:25,0:25:60:0,60,900 0/0:40,0:40:99:0,105,1575 0/0:22,0:22:63:0,63,914 0/0:36,0:36:87:0,87,1530 0/0:21,0:21:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:20,0:20:60:0,60,676 0/0:22,0:22:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:39,0:39:87:0,87,1440 0/0:26,0:26:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,811 0/0:32,0:32:60:0,60,900 0/0:43,0:43:99:0,120,1800 0/0:22,0:22:60:0,60,900 0/0:9,0:9:27:0,27,336 0/0:32,0:32:75:0,75,1125 0/0:33,0:33:84:0,84,1260 0/0:21,0:21:60:0,60,811 0/0:23,0:23:60:0,60,794 0/0:30,0:30:60:0,60,900 0/0:20,0:20:60:0,60,703 0/0:20,0:20:60:0,60,735 0/0:23,0:23:63:0,63,887 0/0:12,0:12:33:0,33,474 0/0:30,0:30:63:0,63,945 0/0:22,0:22:60:0,60,815 0/0:29,0:29:69:0,69,1035 +20 16719564 . G T 801.33 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.39;AN=200;InbreedingCoeff=-0.0019;AF=0.001149;GQ_STDDEV=26.49;FS=0.989;DP=18476;GQ_MEAN=53.51;VQSLOD=2.7;ClippingRankSum=2.44;BaseQRankSum=-0.454;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=11.45;MQRankSum=-0.124;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,885 0/0:22,0:22:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:27,0:27:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:7,0:7:21:0,21,242 0/0:21,0:21:60:0,60,785 0/0:16,0:16:39:0,39,585 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:8,11:19:99:301,0,202 0/0:27,0:27:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:31,0:31:66:0,66,990 0/1:29,22:51:99:577,0,810 0/0:27,0:27:66:0,66,990 0/0:45,0:45:99:0,108,1620 0/0:35,0:35:68:0,68,1282 0/0:36,0:36:90:0,90,1350 0/0:28,0:28:72:0,72,1080 0/0:21,0:21:60:0,60,861 0/0:21,0:21:63:0,63,651 0/0:21,0:21:60:0,60,859 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:30,0:30:80:0,80,1215 0/0:26,0:26:66:0,66,981 0/0:21,0:21:60:0,60,810 0/0:17,0:17:42:0,42,630 0/0:35,0:35:81:0,81,1215 0/0:34,0:34:63:0,63,945 0/0:31,0:31:75:0,75,1125 0/0:22,0:22:66:0,66,705 0/0:20,0:20:60:0,60,702 0/0:34,0:34:81:0,81,1215 0/0:23,0:23:60:0,60,900 0/0:12,0:12:30:0,30,450 0/0:13,0:13:22:0,22,405 0/0:23,0:23:60:0,60,900 0/0:13,0:13:24:0,24,405 0/0:21,0:21:60:0,60,878 0/0:20,0:20:48:0,48,720 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:17,0:17:39:0,39,585 0/0:12,0:12:30:0,30,450 0/0:21,0:21:57:0,57,855 0/0:21,0:21:51:0,51,765 0/0:20,0:20:60:0,60,749 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,761 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,749 0/0:39,0:39:99:0,105,1575 0/0:24,0:24:63:0,63,945 0/0:23,0:23:63:0,63,843 0/0:43,0:43:85:0,85,1800 0/0:10,0:10:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:36,0:36:86:0,86,1395 0/0:21,0:21:60:0,60,900 0/0:28,0:28:66:0,66,980 0/0:9,0:9:22:0,22,331 0/0:24,0:24:60:0,60,900 0/0:14,0:14:36:0,36,540 0/0:12,0:12:30:0,30,450 0/0:11,0:11:24:0,24,360 0/0:13,0:13:30:0,30,450 0/0:15,0:15:36:0,36,540 0/0:26,0:26:65:0,65,867 0/0:22,0:22:60:0,60,900 0/0:15,0:15:33:0,33,495 0/0:32,0:32:79:0,79,1215 0/0:21,0:21:60:0,60,701 0/0:21,0:21:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:12,0:12:27:0,27,405 0/0:11,0:11:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:22,0:22:60:0,60,843 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,837 0/0:22,0:22:60:0,60,900 +20 16721653 rs1804873 T C 8537.22 PASS HWP=1.0;AC=4;culprit=FS;MQ0=0;ReadPosRankSum=0.839;AN=200;InbreedingCoeff=-0.0052;AF=0.005172;GQ_STDDEV=91.56;FS=3.682;DP=24330;GQ_MEAN=76.73;POSITIVE_TRAIN_SITE;VQSLOD=4.38;ClippingRankSum=-0.387;BaseQRankSum=4.26;MLEAF=0.005172;MLEAC=9;MQ=59.66;QD=15.55;DB;MQRankSum=0.281;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:21,0:21:60:0,60,745 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,724 0/0:21,0:21:63:0,63,871 0/0:20,0:20:60:0,60,774 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:22,0:22:63:0,63,866 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,807 0/0:28,0:28:78:0,78,1169 0/0:28,0:28:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:22,0:22:60:0,60,900 0/0:33,0:33:81:0,81,1215 0/0:21,0:21:60:0,60,900 0/0:32,0:32:77:0,77,1170 0/0:22,0:22:60:0,60,900 0/0:30,0:30:69:0,69,1205 0/0:33,0:33:60:0,60,900 0/0:38,0:38:69:0,69,1035 0/0:26,0:26:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:32,0:32:61:0,61,1080 0/0:22,0:22:60:0,60,860 0/0:20,0:20:60:0,60,733 0/0:22,0:22:60:0,60,820 0/0:47,0:47:99:0,99,1485 0/0:69,0:69:99:0,120,1800 0/0:53,0:53:99:0,99,1485 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,688 0/0:23,0:23:69:0,69,879 0/0:25,0:25:63:0,63,945 0/0:32,0:32:96:0,96,1246 0/0:26,0:26:66:0,66,990 0/0:35,0:35:78:0,78,1170 0/1:22,22:44:99:760,0,707 0/0:34,0:34:84:0,84,1260 0/0:36,0:36:75:0,75,1125 0/0:36,0:36:87:0,87,1305 0/0:35,0:35:72:0,72,1080 0/0:36,0:36:84:0,84,1260 0/0:37,0:37:78:0,78,1170 0/0:40,0:40:87:0,87,1305 0/0:30,0:30:75:0,75,1125 0/1:33,32:65:99:1071,0,962 0/0:29,0:29:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:35,0:35:84:0,84,1260 0/0:51,0:51:99:0,117,1755 0/0:36,0:36:75:0,75,1125 0/0:31,0:31:63:0,63,945 0/0:44,0:44:95:0,95,1440 0/0:31,0:31:60:0,60,900 0/0:26,0:26:66:0,66,990 0/1:59,47:106:99:1690,0,1765 0/1:29,25:54:99:839,0,836 0/0:29,0:29:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,806 0/0:23,0:23:60:0,60,900 0/0:36,0:36:99:0,99,1485 0/0:31,0:31:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:35,0:35:84:0,84,1260 0/0:23,0:23:60:0,60,945 0/0:28,0:28:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:63:0,63,939 0/0:25,0:25:60:0,60,900 0/0:27,0:27:72:0,72,1075 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,799 0/0:23,0:23:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,763 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:47,0:47:99:0,105,1575 0/0:20,0:20:60:0,60,729 0/0:22,0:22:63:0,63,846 0/0:25,0:25:60:0,60,900 0/0:21,0:21:63:0,63,796 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,872 0/0:20,0:20:60:0,60,732 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,861 0/0:29,0:29:64:0,64,990 +20 16729016 rs17686413 C G 59926.30 PASS HWP=1.0;AC=8;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.647;AN=200;InbreedingCoeff=-0.0259;AF=0.025;GQ_STDDEV=292.24;FS=2.051;DP=51108;GQ_MEAN=160.93;POSITIVE_TRAIN_SITE;VQSLOD=4.26;ClippingRankSum=0.0;BaseQRankSum=2.74;MLEAF=0.025;MLEAC=44;MQ=60.0;QD=15.83;DB;MQRankSum=-0.058;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:44,0:44:99:0,108,1620 0/0:52,0:52:99:0,120,1800 0/0:40,0:40:96:0,96,1440 0/0:45,0:45:99:0,114,1710 0/0:56,0:56:99:0,120,1800 0/0:58,0:58:99:0,114,1710 0/0:58,0:58:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:47,0:47:99:0,111,1665 0/0:36,0:36:87:0,87,1305 0/0:34,0:34:72:0,72,1080 0/0:50,0:50:99:0,108,1620 0/1:49,43:92:99:1478,0,1539 0/0:38,0:38:99:0,99,1485 0/0:48,0:48:92:0,92,1485 0/0:35,0:35:81:0,81,1215 0/1:34,35:69:99:1094,0,1088 0/0:36,0:36:88:0,88,1321 0/0:72,0:72:99:0,120,1800 0/0:39,0:39:72:0,72,1080 0/0:47,0:47:99:0,108,1620 0/0:42,0:42:99:0,99,1485 0/0:45,0:45:99:0,102,1530 0/0:39,0:39:81:0,81,1215 0/0:56,0:56:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:42,0:42:93:0,93,1769 0/0:107,0:107:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:24,0:24:60:0,60,900 0/0:33,0:33:72:0,72,1080 0/0:33,0:33:72:0,72,1080 0/0:60,0:60:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:45,0:45:96:0,96,1440 0/0:52,0:52:99:0,99,1485 0/0:33,0:33:72:0,72,1080 0/0:71,0:71:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/1:50,55:105:99:1814,0,1634 0/0:62,0:62:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:43,0:43:78:0,78,1170 0/0:51,0:51:99:0,120,1800 0/1:77,60:137:99:2110,0,2781 0/0:67,0:67:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/1:39,53:92:99:1873,0,1306 0/0:102,0:102:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/1:33,26:59:99:972,0,1188 0/0:46,0:46:99:0,111,1755 0/0:97,0:97:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/0:108,0:108:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/1:37,41:78:99:1538,0,1235 0/0:44,0:44:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/1:44,40:84:99:1460,0,1618 0/0:27,0:27:60:0,60,900 0/0:34,0:34:89:0,89,1485 0/0:32,0:32:75:0,75,1125 0/0:74,0:74:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:42,0:42:99:0,120,1800 0/0:30,0:30:90:0,90,1155 0/0:44,0:44:99:0,105,1575 0/0:86,0:86:99:0,120,1800 0/0:33,0:33:60:0,60,900 0/0:48,0:48:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:41,0:41:99:0,113,1755 0/0:39,0:39:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:39,0:39:72:0,72,1080 0/0:72,0:72:99:0,120,1800 0/0:34,0:34:63:0,63,945 0/0:76,0:76:99:0,120,1800 +20 16729048 rs17686437 T C 101969.00 PASS HWP=1.0;AC=8;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.05;AN=200;InbreedingCoeff=-0.0259;AF=0.025;GQ_STDDEV=499.24;FS=0.686;DP=54655;GQ_MEAN=206.07;POSITIVE_TRAIN_SITE;VQSLOD=4.42;ClippingRankSum=0.23;BaseQRankSum=4.22;MLEAF=0.025;MLEAC=44;MQ=59.76;QD=13.87;DB;MQRankSum=0.142;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:44,0:44:99:0,108,1620 0/0:52,0:52:99:0,120,1800 0/0:40,0:40:96:0,96,1440 0/0:45,0:45:99:0,114,1710 0/0:56,0:56:99:0,120,1800 0/0:58,0:58:99:0,114,1710 0/0:58,0:58:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:47,0:47:99:0,111,1665 0/0:36,0:36:87:0,87,1305 0/0:34,0:34:72:0,72,1080 0/0:50,0:50:99:0,108,1620 0/1:81,82:163:99:2460,0,2286 0/0:38,0:38:99:0,99,1485 0/0:48,0:48:92:0,92,1485 0/0:35,0:35:81:0,81,1215 0/1:60,76:136:99:2164,0,1701 0/0:36,0:36:88:0,88,1321 0/0:72,0:72:99:0,120,1800 0/0:39,0:39:72:0,72,1080 0/0:47,0:47:99:0,108,1620 0/0:42,0:42:99:0,99,1485 0/0:45,0:45:99:0,102,1530 0/0:39,0:39:81:0,81,1215 0/0:56,0:56:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:42,0:42:93:0,93,1769 0/0:107,0:107:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:24,0:24:60:0,60,900 0/0:33,0:33:72:0,72,1080 0/0:33,0:33:72:0,72,1080 0/0:60,0:60:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:45,0:45:96:0,96,1440 0/0:52,0:52:99:0,99,1485 0/0:33,0:33:72:0,72,1080 0/0:71,0:71:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/1:98,104:202:99:3002,0,2747 0/0:62,0:62:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:43,0:43:78:0,78,1170 0/0:51,0:51:99:0,120,1800 0/1:138,120:258:99:3878,0,3889 0/0:67,0:67:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/1:74,76:150:99:2205,0,2094 0/0:102,0:102:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/1:66,53:119:99:1682,0,1994 0/0:46,0:46:99:0,111,1755 0/0:97,0:97:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/0:108,0:108:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/1:78,96:174:99:3019,0,2153 0/0:44,0:44:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/1:86,68:154:99:2190,0,2415 0/0:27,0:27:60:0,60,900 0/0:34,0:34:89:0,89,1485 0/0:32,0:32:75:0,75,1125 0/0:74,0:74:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:42,0:42:99:0,120,1800 0/0:30,0:30:90:0,90,1155 0/0:44,0:44:99:0,105,1575 0/0:86,0:86:99:0,120,1800 0/0:33,0:33:60:0,60,900 0/0:48,0:48:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:41,0:41:99:0,113,1755 0/0:39,0:39:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:39,0:39:72:0,72,1080 0/0:72,0:72:99:0,120,1800 0/0:34,0:34:63:0,63,945 0/0:76,0:76:99:0,120,1800 +20 16729138 rs6135876 T C 1137990.00 PASS HWP=0.3024;AC=28;culprit=FS;MQ0=0;ReadPosRankSum=0.705;AN=200;InbreedingCoeff=0.0382;AF=0.186;GQ_STDDEV=1449.53;FS=0.0;DP=97312;GQ_MEAN=981.21;POSITIVE_TRAIN_SITE;VQSLOD=6.92;ClippingRankSum=-0.548;BaseQRankSum=3.48;MLEAF=0.186;MLEAC=323;MQ=59.65;QD=16.95;DB;MQRankSum=0.265;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:44,0:44:99:0,108,1620 0/1:119,107:226:99:3008,0,3245 0/0:40,0:40:96:0,96,1440 0/0:45,0:45:99:0,114,1710 0/0:56,0:56:99:0,120,1800 0/0:58,0:58:99:0,114,1710 0/0:58,0:58:99:0,120,1800 0/1:102,103:205:99:2777,0,2692 0/0:44,0:44:99:0,102,1530 0/0:47,0:47:99:0,111,1665 0/0:36,0:36:87:0,87,1305 0/0:34,0:34:72:0,72,1080 0/0:50,0:50:99:0,108,1620 0/1:122,113:235:99:3132,0,3220 0/0:38,0:38:99:0,99,1485 0/0:48,0:48:92:0,92,1485 0/0:35,0:35:81:0,81,1215 0/1:101,95:196:99:2504,0,2850 0/0:36,0:36:88:0,88,1321 0/1:100,116:216:99:3377,0,2848 0/0:39,0:39:72:0,72,1080 0/0:47,0:47:99:0,108,1620 0/0:42,0:42:99:0,99,1485 0/0:45,0:45:99:0,102,1530 0/0:39,0:39:81:0,81,1215 0/0:56,0:56:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/1:159,174:333:99:5157,0,4437 0/0:66,0:66:99:0,120,1800 0/1:113,115:228:99:3296,0,2933 0/0:107,0:107:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:24,0:24:60:0,60,900 0/0:33,0:33:72:0,72,1080 0/0:33,0:33:72:0,72,1080 0/0:60,0:60:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:45,0:45:96:0,96,1440 0/0:52,0:52:99:0,99,1485 0/0:33,0:33:72:0,72,1080 0/1:85,80:165:99:2533,0,2646 0/1:81,90:171:99:2474,0,2316 0/0:77,0:77:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:83,0:83:99:0,120,1800 1/1:3,266:269:99:10220,724,0 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:43,0:43:78:0,78,1170 0/0:51,0:51:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/1:97,92:189:99:2930,0,3000 0/0:78,0:78:99:0,120,1800 0/1:149,137:286:99:4257,0,4542 0/1:82,85:167:99:2494,0,2573 0/0:71,0:71:99:0,120,1800 0/0:102,0:102:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:28,0:28:63:0,63,945 0/1:68,58:126:99:1864,0,2024 0/0:97,0:97:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/1:148,143:291:99:4414,0,4284 0/0:51,0:51:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/1:90,103:193:99:3357,0,2742 0/0:53,0:53:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/1:83,91:174:99:2845,0,2469 0/0:44,0:44:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/1:56,64:120:99:1997,0,1662 0/0:32,0:32:75:0,75,1125 0/1:104,103:207:99:3299,0,3078 0/1:103,79:182:99:2432,0,3163 1/1:2,282:284:99:10570,824,0 0/1:131,110:241:99:3122,0,3376 0/1:118,106:224:99:2818,0,3118 0/0:44,0:44:99:0,105,1575 0/0:86,0:86:99:0,120,1800 0/0:33,0:33:60:0,60,900 0/1:106,129:235:99:3586,0,2659 0/0:61,0:61:99:0,120,1800 0/1:77,55:132:99:1630,0,2364 0/0:39,0:39:75:0,75,1125 0/0:27,0:27:60:0,60,900 0/0:39,0:39:72:0,72,1080 0/1:87,86:173:99:2839,0,2629 0/0:34,0:34:63:0,63,945 0/0:76,0:76:99:0,120,1800 +20 16729654 rs10627353 A AAGATG 1227240.00 VQSRTrancheINDEL96.00to97.00 HWP=0.1023;AC=146;culprit=MQRankSum;MQ0=0;ReadPosRankSum=-0.649;AN=200;InbreedingCoeff=0.0593;AF=0.745;GQ_STDDEV=393.03;FS=3.671;DP=42868;GQ_MEAN=349.16;POSITIVE_TRAIN_SITE;VQSLOD=0.872;ClippingRankSum=-0.259;BaseQRankSum=2.07;MLEAF=0.746;MLEAC=1298;MQ=40.21;QD=19.9;DB;MQRankSum=-4.484;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,39:39:99:1800,122,0 1/1:0,36:36:99:1828,118,0 1/1:0,31:31:99:1493,99,0 1/1:0,43:43:99:1902,126,0 1/1:0,33:33:99:1579,104,0 1/1:0,53:53:99:2340,154,0 1/1:0,44:44:99:2010,132,0 1/1:0,26:26:74:1162,74,0 1/1:0,41:41:99:1874,123,0 1/1:0,38:38:99:1678,113,0 1/1:1,24:25:80:1208,80,0 1/1:0,27:27:84:1290,84,0 0/0:24,0:24:60:0,60,864 1/1:0,27:27:79:1185,79,0 1/1:0,33:33:99:1486,101,0 0/0:21,0:21:60:0,60,900 0/1:28,18:46:99:694,0,1873 1/1:0,58:58:99:2657,176,0 0/1:28,13:41:99:457,0,1860 1/1:0,65:65:99:3038,197,0 0/1:32,27:59:99:1049,0,2150 0/1:45,24:69:99:802,0,2963 0/0:20,0:20:60:0,60,751 0/1:48,32:80:99:1158,0,3137 0/0:22,0:22:63:0,63,945 0/1:26,22:48:99:916,0,1662 0/1:30,29:59:99:1075,0,1899 0/0:30,0:30:81:0,81,1089 0/0:22,0:22:63:0,63,746 1/1:0,36:36:99:1720,114,0 1/1:0,25:25:77:1187,77,0 1/1:0,44:44:99:1971,128,0 0/1:49,47:96:99:1859,0,3173 1/1:0,112:112:99:5116,335,0 1/1:0,74:74:99:3461,225,0 0/1:27,15:42:99:587,0,1810 1/1:0,28:28:84:1249,84,0 0/1:24,22:46:99:845,0,1580 1/1:0,54:54:99:2535,168,0 1/1:0,66:66:99:2975,196,0 0/0:25,0:25:63:0,63,901 0/1:31,26:57:99:1103,0,2013 1/1:0,43:43:99:2002,130,0 1/1:0,40:40:99:1905,125,0 0/1:36,34:70:99:1368,0,2374 1/1:0,68:68:99:2973,196,0 0/1:34,28:62:99:1100,0,2276 0/1:38,28:66:99:1030,0,2431 1/1:1,61:62:99:2693,108,0 1/1:0,67:67:99:3063,201,0 0/1:22,21:43:99:829,0,1484 1/1:0,34:34:97:1453,97,0 0/1:22,28:50:99:1045,0,1428 0/1:38,17:55:99:594,0,2467 1/1:0,67:67:99:3144,205,0 0/1:42,36:78:99:1406,0,2569 1/1:0,62:62:99:2896,189,0 0/1:36,36:72:99:1540,0,2366 0/1:43,29:72:99:1056,0,2897 1/1:0,67:67:99:3064,200,0 1/1:0,54:54:99:2562,167,0 0/1:33,17:50:99:684,0,2194 0/0:36,0:36:99:0,105,1575 0/1:32,24:56:99:884,0,2089 1/1:0,62:62:99:2795,184,0 0/1:31,21:52:99:767,0,2101 1/1:0,31:31:89:1371,89,0 0/1:28,18:46:99:710,0,1881 0/1:42,28:70:99:1188,0,2659 0/1:26,19:45:99:691,0,1759 1/1:3,71:74:99:3284,217,0 0/1:41,27:68:99:1022,0,2745 0/0:24,0:24:60:0,60,900 1/1:0,40:40:99:1892,124,0 0/1:41,18:59:99:662,0,2719 0/1:20,18:38:99:719,0,1297 1/1:0,58:58:99:2737,180,0 0/0:22,0:22:60:0,60,900 1/1:0,46:46:99:2136,138,0 1/1:0,40:40:99:1779,118,0 0/1:20,14:34:99:549,0,1367 1/1:0,44:44:99:1968,132,0 1/1:0,30:30:92:1421,92,0 1/1:0,62:62:99:2837,186,0 1/1:0,43:43:99:2011,133,0 1/1:0,60:60:99:2777,182,0 1/1:0,25:25:74:1150,74,0 1/1:0,41:41:99:1864,122,0 1/1:0,51:51:99:2356,157,0 0/1:49,37:86:99:1512,0,3198 0/1:34,27:61:99:1047,0,2099 1/1:0,37:37:99:1678,110,0 0/1:25,25:50:99:998,0,1633 1/1:0,29:29:87:1335,87,0 1/1:0,36:36:99:1636,106,0 1/1:0,28:28:84:1273,84,0 1/1:0,36:36:99:1707,112,0 1/1:2,39:41:14:1766,14,0 1/1:0,38:38:99:1697,108,0 0/1:39,25:64:99:1136,0,2592 +20 16730522 rs6135878 T C 410524.00 PASS HWP=0.0;AC=100;culprit=FS;MQ0=0;ReadPosRankSum=0.32;AN=200;InbreedingCoeff=0.2054;AF=0.484;GQ_STDDEV=194.59;FS=0.0;DP=21891;GQ_MEAN=180.2;POSITIVE_TRAIN_SITE;VQSLOD=4.34;ClippingRankSum=-0.102;BaseQRankSum=0.731;MLEAF=0.487;MLEAC=847;MQ=59.03;QD=24.2;DB;MQRankSum=-0.024;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:20,0:20:60:0,60,718 0/1:8,13:21:99:439,0,249 0/0:33,0:33:22:0,22,1043 1/1:0,36:36:99:1258,108,0 0/1:13,4:17:99:103,0,434 0/1:16,13:29:99:352,0,507 0/0:12,0:12:36:0,36,445 0/1:13,12:25:99:373,0,423 0/0:22,0:22:62:0,62,945 1/1:0,30:30:90:1012,90,0 0/1:13,15:28:99:433,0,397 0/1:13,12:25:99:385,0,320 0/1:23,10:33:99:282,0,734 0/1:10,12:22:99:361,0,270 0/0:7,0:7:21:0,21,251 0/1:10,5:15:99:116,0,321 0/0:9,0:9:22:0,22,345 0/1:6,10:16:99:270,0,186 0/1:6,12:18:99:386,0,147 0/1:18,15:33:99:445,0,541 0/0:8,0:8:24:0,24,308 0/1:7,7:14:99:197,0,226 0/0:13,0:13:36:0,36,491 0/1:13,34:47:99:1123,0,367 0/0:26,0:26:63:0,63,945 0/0:20,0:20:60:0,60,754 0/1:19,17:36:99:469,0,552 0/0:20,0:20:60:0,60,774 0/0:21,0:21:60:0,60,900 0/1:14,12:26:99:366,0,467 0/0:11,0:11:30:0,30,388 0/1:13,19:32:99:572,0,436 0/1:28,25:53:99:777,0,879 1/1:0,64:64:99:2377,192,0 0/1:20,47:67:99:1507,0,560 0/0:11,0:11:30:0,30,450 0/0:21,0:21:60:0,60,768 0/1:7,12:19:99:395,0,171 0/1:17,17:34:99:537,0,578 1/1:0,40:40:99:1454,120,0 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 1/1:0,19:19:57:741,57,0 1/1:0,31:31:93:1176,93,0 0/1:16,27:43:99:814,0,511 0/0:25,0:25:72:0,72,949 0/0:20,0:20:60:0,60,750 0/1:25,26:51:99:793,0,816 1/1:0,40:40:99:1537,120,0 0/1:23,26:49:99:816,0,744 0/0:25,0:25:63:0,63,945 0/1:12,18:30:99:535,0,361 0/1:13,17:30:99:500,0,420 0/1:13,9:22:99:267,0,468 0/1:24,15:39:99:405,0,733 0/1:14,21:35:99:666,0,428 0/1:21,18:39:99:584,0,677 0/1:16,21:37:99:662,0,493 0/1:11,20:31:99:684,0,316 1/1:2,35:37:62:1314,62,0 1/1:0,14:14:42:528,42,0 0/0:21,0:21:60:0,60,733 0/1:44,35:79:99:1064,0,1321 1/1:0,36:36:99:1261,108,0 0/1:5,11:16:99:344,0,150 0/1:11,8:19:99:234,0,372 0/1:12,3:15:68:68,0,402 0/0:7,0:7:21:0,21,267 1/1:1,50:51:99:1933,113,0 0/0:21,0:21:60:0,60,900 1/1:2,28:30:46:1090,46,0 1/1:0,27:27:81:1082,81,0 0/0:24,0:24:60:0,60,900 1/1:0,20:20:60:790,60,0 0/1:9,22:31:99:743,0,226 0/1:16,16:32:99:483,0,454 0/1:7,3:10:99:100,0,258 0/0:7,0:7:21:0,21,257 1/1:0,15:15:45:555,45,0 0/1:12,17:29:99:587,0,328 0/0:13,0:13:39:0,39,491 1/1:0,13:13:39:555,39,0 0/1:12,7:19:99:201,0,427 1/1:0,26:26:78:1057,78,0 0/1:19,13:32:99:390,0,630 1/1:0,37:37:99:1409,111,0 0/1:8,12:20:99:358,0,223 1/1:0,23:23:69:881,69,0 0/1:13,9:22:99:267,0,383 0/1:20,19:39:99:670,0,665 0/1:15,13:28:99:428,0,387 1/1:0,35:35:99:1215,105,0 1/1:0,16:16:48:653,48,0 1/1:0,20:20:60:841,60,0 1/1:0,30:30:90:1187,90,0 1/1:0,23:23:69:794,69,0 0/1:8,6:14:99:177,0,274 1/1:0,22:22:66:783,66,0 1/1:0,13:13:39:481,39,0 0/1:18,16:34:99:550,0,554 +20 17349844 . T G 16173.60 VQSRTrancheSNP99.90to99.95 HWP=3.0E-4;AC=21;culprit=FS;MQ0=0;ReadPosRankSum=0.961;AN=170;InbreedingCoeff=-0.2461;AF=0.123;GQ_STDDEV=40.48;FS=58.11;DP=11809;GQ_MEAN=31.95;VQSLOD=-23.11;ClippingRankSum=-0.537;BaseQRankSum=-1.817;MLEAF=0.173;MLEAC=276;MQ=60.0;QD=4.76;MQRankSum=0.206;CCC=1598;NCC=71 GT:AD:DP:GQ:PL 0/0:18,0:18:15:0,15,475 0/0:9,0:9:27:0,27,345 0/0:16,0:16:21:0,21,519 0/0:20,0:20:17:0,17,570 0/0:15,0:15:39:0,39,585 0/0:32,0:32:73:0,73,986 0/0:16,0:16:21:0,21,485 0/0:19,0:19:57:0,57,563 0/0:15,0:15:33:0,33,469 0/0:20,0:20:52:0,52,585 0/0:16,0:16:24:0,24,553 0/0:11,0:11:33:0,33,427 0/0:20,0:20:0:0,0,410 0/0:16,0:16:28:0,28,462 0/0:9,0:9:21:0,21,261 0/0:18,0:18:54:0,54,528 0/0:16,0:16:15:0,15,407 0/0:22,0:22:19:0,19,574 0/0:12,0:12:0:0,0,275 0/0:17,0:17:51:0,51,531 0/0:13,0:13:23:0,23,355 0/0:21,0:21:18:0,18,493 0/0:19,0:19:40:0,40,559 0/1:12,5:17:50:50,0,390 0/1:22,7:29:49:49,0,654 ./.:18,0:18:.:. 0/0:11,0:11:0:0,0,129 0/0:11,0:11:0:0,0,25 0/0:11,0:11:9:0,9,258 0/1:9,10:19:99:151,0,169 0/0:18,0:18:30:0,30,505 0/1:10,5:15:23:23,0,240 ./.:13,0:13:.:. ./.:5,0:5:.:. 0/1:7,5:12:85:85,0,199 0/0:10,0:10:10:0,10,266 0/0:20,0:20:0:0,0,435 0/0:15,0:15:39:0,39,459 0/1:6,3:9:42:42,0,179 0/0:13,0:13:0:0,0,133 0/0:5,0:5:0:0,0,27 0/0:8,0:8:0:0,0,152 0/0:9,0:9:0:0,0,97 0/1:7,7:14:97:97,0,172 ./.:10,0:10:.:. 0/0:14,0:14:0:0,0,90 ./.:11,0:11:.:. 0/0:14,0:14:0:0,0,41 0/1:6,4:10:55:55,0,169 0/0:11,0:11:0:0,0,236 0/0:13,0:13:0:0,0,198 ./.:9,0:9:.:. 0/0:7,0:7:0:0,0,112 0/0:4,0:4:6:0,6,90 0/0:4,0:4:6:0,6,90 0/0:11,0:11:10:0,10,310 0/0:10,0:10:0:0,0,281 ./.:14,0:14:.:. 0/0:9,0:9:0:0,0,47 0/1:10,7:17:74:74,0,281 0/1:4,2:6:36:36,0,105 0/0:7,0:7:0:0,0,177 ./.:12,0:12:.:. 0/0:8,0:8:0:0,0,123 0/1:3,3:6:29:29,0,87 0/0:12,0:12:2:0,2,304 0/0:3,0:3:0:0,0,28 ./.:2,0:2:.:. 0/1:4,8:12:96:176,0,96 ./.:7,0:7:.:. 0/1:6,7:13:90:90,0,166 ./.:9,0:9:.:. 0/1:6,4:10:30:30,0,168 ./.:3,0:3:.:. 0/0:9,0:9:0:0,0,9 0/1:2,10:12:20:231,0,20 0/0:3,0:3:0:0,0,54 0/0:5,0:5:0:0,0,40 ./.:11,0:11:.:. 0/0:8,0:8:0:0,0,81 0/0:4,0:4:0:0,0,15 0/0:5,0:5:0:0,0,49 0/0:5,0:5:0:0,0,2 0/0:10,0:10:0:0,0,126 0/0:5,0:5:9:0,9,135 1/1:0,5:5:14:111,14,0 0/0:12,0:12:0:0,0,273 0/0:14,0:14:36:0,36,411 0/0:11,0:11:21:0,21,334 0/0:9,0:9:0:0,0,50 0/0:18,0:18:1:0,1,436 0/1:14,10:24:72:72,0,306 ./.:7,0:7:.:. 0/0:7,0:7:0:0,0,109 0/1:9,9:18:36:36,0,234 0/1:11,6:17:9:9,0,268 0/0:5,0:5:0:0,0,108 0/1:3,10:13:64:222,0,64 ./.:5,0:5:.:. 0/0:11,0:11:0:0,0,133 +20 17389877 rs2859875 C T 301670.00 PASS HWP=0.0067;AC=14;culprit=FS;MQ0=0;ReadPosRankSum=0.548;AN=200;InbreedingCoeff=0.1016;AF=0.128;GQ_STDDEV=514.87;FS=0.0;DP=56427;GQ_MEAN=338.99;POSITIVE_TRAIN_SITE;VQSLOD=7.4;ClippingRankSum=-0.094;BaseQRankSum=-4.212;MLEAF=0.128;MLEAC=222;MQ=59.83;QD=16.34;DB;MQRankSum=0.192;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:51,0:51:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:42,0:42:96:0,96,1440 0/0:74,0:74:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/1:29,23:52:99:684,0,837 0/0:36,0:36:78:0,78,1170 0/0:48,0:48:99:0,117,1755 0/0:55,0:55:99:0,120,1800 0/1:34,33:67:99:1022,0,1074 0/1:35,42:77:99:1229,0,1076 0/0:50,0:50:99:0,120,1800 0/0:48,0:48:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/1:78,67:145:99:2081,0,2607 0/0:44,0:44:99:0,99,1485 0/0:57,0:57:99:0,120,1800 0/1:44,45:89:99:1370,0,1350 0/0:60,0:60:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:46,0:46:99:0,99,1485 0/1:49,60:109:99:1736,0,1617 0/0:107,0:107:99:0,120,1800 0/0:110,0:110:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:26,0:26:66:0,66,990 0/1:48,37:85:99:1052,0,1675 0/0:54,0:54:99:0,120,1800 0/1:35,42:77:99:1293,0,1039 0/0:68,0:68:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:41,0:41:99:0,105,1575 0/0:50,0:50:99:0,118,1773 0/0:56,0:56:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/1:49,43:92:99:1255,0,1608 0/1:42,29:71:99:832,0,1345 0/0:59,0:59:99:0,120,1800 0/0:49,0:49:99:0,114,1710 0/0:63,0:63:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/1:46,46:92:99:1416,0,1396 0/0:71,0:71:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/1:50,43:93:99:1205,0,1670 0/0:55,0:55:99:0,120,1800 0/0:29,0:29:84:0,84,1260 0/0:24,0:24:60:0,60,900 0/0:122,0:122:99:0,120,1800 0/0:30,0:30:63:0,63,945 0/0:68,0:68:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/1:77,68:145:99:1918,0,2461 0/0:56,0:56:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:40,0:40:73:0,73,1395 0/0:61,0:61:99:0,120,1800 0/1:44,31:75:99:842,0,1536 0/0:49,0:49:99:0,111,1665 0/0:52,0:52:99:0,120,1800 0/0:28,0:28:84:0,84,1037 0/0:39,0:39:98:0,98,1530 0/0:40,0:40:78:0,78,1170 0/0:58,0:58:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:36,0:36:90:0,90,1350 0/0:38,0:38:66:0,66,990 0/0:43,0:43:90:0,90,1440 0/0:82,0:82:99:0,120,1800 0/0:45,0:45:96:0,96,1440 0/0:45,0:45:99:0,108,1620 0/0:58,0:58:99:0,120,1800 0/0:31,0:31:60:0,60,900 0/0:37,0:37:78:0,78,1170 0/0:32,0:32:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:34,0:34:87:0,87,1305 0/0:34,0:34:84:0,84,1218 0/0:50,0:50:99:0,102,1530 +20 17410116 rs41276380 C T 20246.10 PASS HWP=1.0;AC=3;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.97;AN=200;InbreedingCoeff=-0.0046;AF=0.004598;GQ_STDDEV=241.46;FS=0.0;DP=35161;GQ_MEAN=104.83;POSITIVE_TRAIN_SITE;VQSLOD=4.07;ClippingRankSum=-1.967;BaseQRankSum=3.62;MLEAF=0.004598;MLEAC=8;MQ=59.75;QD=12.95;DB;MQRankSum=0.476;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:39,0:39:96:0,96,1440 0/0:41,0:41:96:0,96,1440 0/0:24,0:24:60:0,60,900 0/0:36,0:36:84:0,84,1260 0/0:48,0:48:99:0,99,1485 0/0:41,0:41:96:0,96,1440 0/0:44,0:44:99:0,105,1575 0/0:37,0:37:75:0,75,1125 0/0:50,0:50:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:33,0:33:78:0,78,1170 0/0:45,0:45:99:0,109,1710 0/0:44,0:44:69:0,69,1485 0/0:26,0:26:63:0,63,945 0/0:33,0:33:66:0,66,1142 0/0:39,0:39:93:0,93,1395 0/0:31,0:31:72:0,72,1080 0/0:29,0:29:66:0,66,990 0/0:29,0:29:69:0,69,1035 0/0:54,0:54:99:0,120,1800 0/0:42,0:42:99:0,99,1485 0/0:33,0:33:72:0,72,1080 0/0:49,0:49:99:0,113,1755 0/0:37,0:37:72:0,72,1080 0/0:41,0:41:72:0,72,1080 0/0:38,0:38:84:0,84,1260 0/0:50,0:50:99:0,116,1755 0/0:52,0:52:99:0,120,1800 0/0:38,0:38:78:0,78,1170 0/0:49,0:49:99:0,114,1710 0/0:44,0:44:96:0,96,1440 0/0:36,0:36:66:0,66,990 0/0:55,0:55:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:33,0:33:66:0,66,990 0/0:32,0:32:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:43,0:43:87:0,87,1305 0/0:39,0:39:90:0,90,1350 0/0:35,0:35:83:0,83,1194 0/0:39,0:39:99:0,99,1392 0/1:83,63:146:99:1761,0,2206 0/0:50,0:50:99:0,111,1665 0/0:54,0:54:99:0,120,1800 0/0:28,0:28:69:0,69,1035 0/0:33,0:33:78:0,78,1170 0/0:58,0:58:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:44,0:44:99:0,114,1710 0/0:44,0:44:99:0,99,1485 0/0:32,0:32:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:94,95:189:99:2692,0,2442 0/0:32,0:32:72:0,72,1080 0/0:64,0:64:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:46,0:46:99:0,105,1575 0/0:43,0:43:99:0,99,1485 0/0:69,0:69:99:0,120,1800 0/0:45,0:45:99:0,111,1665 0/0:47,0:47:99:0,108,1620 0/0:46,0:46:99:0,111,1665 0/1:52,57:109:99:1322,0,1465 0/0:34,0:34:60:0,60,900 0/0:74,0:74:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:56,0:56:99:0,120,1800 0/0:32,0:32:72:0,72,1080 0/0:34,0:34:66:0,66,990 0/0:31,0:31:69:0,69,1035 0/0:22,0:22:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:26,0:26:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:32,0:32:81:0,81,1136 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:42,0:42:99:0,102,1530 0/0:27,0:27:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:35,0:35:81:0,81,1215 0/0:82,0:82:99:0,120,1800 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:39,0:39:84:0,84,1260 0/0:30,0:30:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:30,0:30:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:38,0:38:90:0,90,1350 +20 17417513 rs6044812 C T 7449.97 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.302;AN=200;InbreedingCoeff=-0.0147;AF=0.012;GQ_STDDEV=44.96;FS=0.879;DP=18791;GQ_MEAN=54.07;POSITIVE_TRAIN_SITE;VQSLOD=4.47;ClippingRankSum=0.348;BaseQRankSum=1.88;MLEAF=0.012;MLEAC=21;MQ=60.0;QD=13.09;DB;MQRankSum=0.233;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:63:0,63,1035 0/0:28,0:28:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:8,0:8:21:0,21,298 0/0:15,0:15:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:11,0:11:24:0,24,360 0/1:10,12:22:99:375,0,271 0/0:24,0:24:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:31,0:31:66:0,66,990 0/0:36,0:36:60:0,60,900 0/1:8,8:16:99:251,0,219 0/0:13,0:13:30:0,30,450 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:14,0:14:27:0,27,405 0/0:27,0:27:62:0,62,990 0/0:29,0:29:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:9,0:9:21:0,21,286 0/0:10,0:10:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:20,0:20:42:0,42,630 0/0:26,0:26:60:0,60,900 0/0:17,0:17:42:0,42,630 0/0:13,0:13:27:0,27,405 0/0:12,0:12:33:0,33,449 0/0:9,0:9:20:0,20,351 0/0:29,0:29:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,929 0/0:21,0:21:48:0,48,720 0/0:25,0:25:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:24,0:24:61:0,61,945 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:26,0:26:72:0,72,914 0/0:13,0:13:30:0,30,450 0/0:25,0:25:60:0,60,900 0/0:23,0:23:57:0,57,855 0/0:11,0:11:27:0,27,405 0/0:29,0:29:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,296 0/0:10,0:10:21:0,21,315 0/0:27,0:27:60:0,60,900 0/0:10,0:10:24:0,24,360 0/0:26,0:26:63:0,63,945 0/0:8,0:8:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:3,0:3:6:0,6,90 0/0:24,0:24:54:0,54,810 0/0:9,0:9:27:0,27,356 0/0:16,0:16:21:0,21,630 0/0:12,0:12:22:0,22,360 0/0:11,0:11:20:0,20,360 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,311 0/0:8,0:8:21:0,21,315 0/0:8,0:8:21:0,21,288 0/0:15,0:15:32:0,32,540 0/0:20,0:20:45:0,45,675 0/0:22,0:22:51:0,51,765 0/0:21,0:21:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:11,0:11:0:0,0,293 0/0:8,0:8:21:0,21,230 0/0:10,0:10:21:0,21,315 0/0:27,0:27:75:0,75,1125 +20 17434340 . G A 1565.00 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.53;AN=200;InbreedingCoeff=-0.0041;AF=0.002874;GQ_STDDEV=23.74;FS=0.0;DP=19022;GQ_MEAN=52.92;VQSLOD=3.83;ClippingRankSum=-0.412;BaseQRankSum=1.36;MLEAF=0.002874;MLEAC=5;MQ=59.07;QD=16.3;MQRankSum=0.059;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:33,0:33:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:19,0:19:51:0,51,765 0/0:14,0:14:39:0,39,585 0/0:24,0:24:60:0,60,900 0/0:32,0:32:81:0,81,1215 0/0:17,0:17:48:0,48,597 0/0:13,0:13:33:0,33,495 0/0:13,0:13:33:0,33,495 0/0:13,0:13:36:0,36,540 0/0:15,0:15:42:0,42,630 0/0:20,0:20:60:0,60,694 0/0:21,0:21:57:0,57,855 0/0:15,0:15:24:0,24,585 0/0:17,0:17:42:0,42,630 0/0:27,0:27:73:0,73,1111 0/0:37,0:37:99:0,99,1485 0/0:13,0:13:24:0,24,360 0/0:11,0:11:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:65:0,65,1035 0/0:30,0:30:81:0,81,1215 0/0:22,0:22:63:0,63,945 0/0:31,0:31:60:0,60,990 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:13,0:13:39:0,39,485 0/0:28,0:28:60:0,60,900 0/0:11,0:11:30:0,30,447 0/0:20,0:20:27:0,27,405 0/0:22,0:22:50:0,50,810 0/0:12,0:12:21:0,21,315 0/0:11,0:11:27:0,27,405 0/0:8,0:8:24:0,24,311 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:28,0:28:34:0,34,769 0/0:20,0:20:54:0,54,810 0/0:16,0:16:36:0,36,540 0/0:28,0:28:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:18,0:18:27:0,27,405 0/0:14,0:14:30:0,30,450 0/0:14,0:14:42:0,42,593 0/1:10,11:21:99:344,0,248 0/0:12,0:12:24:0,24,360 0/0:25,0:25:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:10,0:10:27:0,27,331 0/0:28,0:28:75:0,75,1046 0/0:21,0:21:60:0,60,900 0/0:14,0:14:21:0,21,405 0/0:52,0:52:99:0,108,1620 0/0:21,0:21:60:0,60,652 0/0:23,0:23:60:0,60,900 0/0:15,0:15:36:0,36,540 0/0:4,0:4:6:0,6,90 0/0:14,0:14:39:0,39,585 0/0:37,0:37:75:0,75,1125 0/0:14,0:14:21:0,21,315 0/0:17,0:17:48:0,48,720 0/0:15,0:15:23:0,23,360 0/0:20,0:20:54:0,54,810 0/0:13,0:13:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:17,0:17:47:0,47,720 0/0:16,0:16:42:0,42,630 0/0:15,0:15:27:0,27,405 0/0:9,0:9:24:0,24,351 0/0:11,0:11:24:0,24,360 0/0:15,0:15:30:0,30,450 0/0:8,0:8:24:0,24,310 0/0:16,0:16:42:0,42,630 0/0:14,0:14:36:0,36,540 0/0:15,0:15:21:0,21,315 0/0:18,0:18:37:0,37,595 0/0:8,0:8:21:0,21,315 0/0:12,0:12:33:0,33,495 0/0:31,0:31:62:0,62,1035 0/0:22,0:22:63:0,63,945 0/0:14,0:14:42:0,42,533 0/0:16,0:16:24:0,24,360 0/0:15,0:15:30:0,30,450 0/0:21,0:21:60:0,60,764 0/0:7,0:7:21:0,21,295 0/0:12,0:12:24:0,24,360 0/0:21,0:21:60:0,60,848 0/0:7,0:7:15:0,15,225 0/0:21,0:21:60:0,60,708 +20 17434572 rs41276384 C T 15425.50 PASS HWP=1.0;AC=3;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.413;AN=200;InbreedingCoeff=-0.0116;AF=0.011;GQ_STDDEV=108.91;FS=2.601;DP=22532;GQ_MEAN=78.33;POSITIVE_TRAIN_SITE;VQSLOD=4.5;ClippingRankSum=-0.138;BaseQRankSum=3.19;MLEAF=0.011;MLEAC=20;MQ=59.7;QD=11.74;DB;MQRankSum=0.22;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:66:0,66,990 0/0:25,0:25:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:33,0:33:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:32,0:32:81:0,81,1215 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,726 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,694 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,898 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,772 0/0:27,0:27:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,772 0/0:20,0:20:60:0,60,753 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,805 0/0:21,0:21:60:0,60,689 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:20,0:20:60:0,60,781 0/0:20,0:20:60:0,60,724 0/0:21,0:21:63:0,63,796 0/0:24,0:24:60:0,60,900 0/1:36,30:66:99:850,0,968 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,740 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:27,0:27:75:0,75,988 0/0:26,0:26:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:24,0:24:60:0,60,891 0/1:31,28:59:99:872,0,805 0/0:22,0:22:63:0,63,772 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,818 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:21,0:21:60:0,60,846 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,900 0/1:20,7:27:99:185,0,653 0/0:33,0:33:75:0,75,1125 0/0:28,0:28:62:0,62,945 0/0:30,0:30:63:0,63,945 0/0:22,0:22:63:0,63,941 0/0:24,0:24:60:0,60,861 0/0:29,0:29:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:20,0:20:60:0,60,696 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,766 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,796 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:21,0:21:63:0,63,869 0/0:28,0:28:66:0,66,990 0/0:21,0:21:60:0,60,724 0/0:22,0:22:60:0,60,873 0/0:20,0:20:60:0,60,656 0/0:29,0:29:60:0,60,900 0/0:31,0:31:62:0,62,1035 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,744 0/0:26,0:26:63:0,63,945 0/0:21,0:21:60:0,60,896 0/0:21,0:21:60:0,60,764 0/0:20,0:20:60:0,60,785 0/0:27,0:27:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 +20 17434581 rs16999198 A G 21384.80 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.534;AN=200;InbreedingCoeff=-0.0134;AF=0.013;GQ_STDDEV=134.2;FS=2.944;DP=22586;GQ_MEAN=83.43;POSITIVE_TRAIN_SITE;VQSLOD=4.77;ClippingRankSum=0.175;BaseQRankSum=4.78;MLEAF=0.013;MLEAC=23;MQ=59.75;QD=14.65;DB;MQRankSum=-0.192;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:66:0,66,990 0/0:25,0:25:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:33,0:33:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:32,33:65:99:1046,0,882 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,726 0/1:19,17:36:99:511,0,544 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,694 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,898 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,772 0/0:27,0:27:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,772 0/0:20,0:20:60:0,60,753 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,805 0/0:21,0:21:60:0,60,689 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:20,0:20:60:0,60,781 0/0:20,0:20:60:0,60,724 0/0:21,0:21:63:0,63,796 0/0:24,0:24:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,740 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:27,0:27:75:0,75,988 0/0:26,0:26:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:24,0:24:60:0,60,891 0/0:32,0:32:60:0,60,900 0/0:22,0:22:63:0,63,772 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,818 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:21,0:21:60:0,60,846 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:33,0:33:75:0,75,1125 0/0:28,0:28:62:0,62,945 0/0:30,0:30:63:0,63,945 0/0:22,0:22:63:0,63,941 0/0:24,0:24:60:0,60,861 0/0:29,0:29:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:20,0:20:60:0,60,696 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,766 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,796 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:21,0:21:63:0,63,869 0/0:28,0:28:66:0,66,990 0/0:21,0:21:60:0,60,724 0/0:22,0:22:60:0,60,873 0/0:20,0:20:60:0,60,656 0/0:29,0:29:60:0,60,900 0/0:31,0:31:62:0,62,1035 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,744 0/0:26,0:26:63:0,63,945 0/0:21,0:21:60:0,60,896 0/0:21,0:21:60:0,60,764 0/0:20,0:20:60:0,60,785 0/0:9,0:9:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:13,0:13:33:0,33,468 0/0:26,0:26:63:0,63,945 +20 17445942 rs41276388 C T 25906.20 PASS HWP=0.1363;AC=8;culprit=MQ;MQ0=0;ReadPosRankSum=0.35;AN=198;InbreedingCoeff=0.0443;AF=0.051;GQ_STDDEV=73.82;FS=3.031;DP=12193;GQ_MEAN=55.89;POSITIVE_TRAIN_SITE;VQSLOD=3.93;ClippingRankSum=0.0;BaseQRankSum=-2.383;MLEAF=0.052;MLEAC=90;MQ=60.0;QD=15.34;DB;MQRankSum=0.174;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:7,0:7:21:0,21,262 0/0:8,0:8:24:0,24,295 0/0:7,0:7:21:0,21,253 0/0:7,0:7:21:0,21,273 0/0:7,0:7:21:0,21,261 0/0:14,0:14:36:0,36,540 0/0:22,0:22:61:0,61,904 0/0:7,0:7:21:0,21,257 0/0:21,0:21:60:0,60,827 0/0:9,0:9:27:0,27,349 0/0:7,0:7:21:0,21,281 0/0:7,0:7:21:0,21,265 0/0:8,0:8:24:0,24,329 0/0:22,0:22:60:0,60,900 0/0:7,0:7:21:0,21,226 0/0:8,0:8:21:0,21,311 0/0:7,0:7:21:0,21,262 0/0:7,0:7:21:0,21,256 0/0:7,0:7:18:0,18,270 0/1:4,6:10:99:197,0,127 0/0:10,0:10:21:0,21,315 0/0:7,0:7:21:0,21,251 0/0:8,0:8:24:0,24,293 0/0:20,0:20:60:0,60,825 0/0:20,0:20:60:0,60,868 0/0:7,0:7:21:0,21,231 0/0:20,0:20:60:0,60,774 0/0:22,0:22:60:0,60,870 0/0:22,0:22:42:0,42,819 0/0:20,0:20:60:0,60,742 0/0:7,0:7:21:0,21,264 0/1:14,13:27:99:417,0,504 0/0:29,0:29:77:0,77,1037 0/0:23,0:23:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:7,0:7:21:0,21,281 0/0:8,0:8:21:0,21,301 0/0:12,0:12:33:0,33,495 0/1:5,14:19:99:434,0,122 0/0:11,0:11:27:0,27,405 0/0:8,0:8:21:0,21,270 0/0:21,0:21:28:0,28,714 0/0:7,0:7:21:0,21,272 0/0:21,0:21:60:0,60,871 0/0:7,0:7:21:0,21,255 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,313 0/0:7,0:7:21:0,21,281 0/0:8,0:8:24:0,24,329 0/0:7,0:7:21:0,21,277 0/0:20,0:20:60:0,60,764 0/1:13,8:21:99:226,0,420 0/0:5,0:5:12:0,12,180 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,298 0/0:10,0:10:30:0,30,344 0/0:24,0:24:60:0,60,900 0/0:9,0:9:27:0,27,325 0/0:21,0:21:60:0,60,823 0/0:7,0:7:21:0,21,255 0/1:8,7:15:99:215,0,268 0/1:15,16:31:99:487,0,451 0/1:15,14:29:99:418,0,515 0/0:8,0:8:21:0,21,315 0/1:9,8:17:99:243,0,278 0/0:7,0:7:21:0,21,259 0/0:7,0:7:21:0,21,256 0/0:4,0:4:12:0,12,164 0/0:20,0:20:60:0,60,838 0/0:7,0:7:21:0,21,266 0/0:7,0:7:21:0,21,244 0/0:7,0:7:21:0,21,286 0/0:8,0:8:24:0,24,276 0/0:7,0:7:21:0,21,281 0/0:7,0:7:21:0,21,255 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,255 0/0:7,0:7:21:0,21,238 0/0:2,0:2:6:0,6,72 0/0:7,0:7:21:0,21,302 0/0:2,0:2:6:0,6,75 0/0:8,0:8:21:0,21,315 0/0:4,0:4:9:0,9,135 0/0:7,0:7:21:0,21,283 0/0:5,0:5:15:0,15,187 0/0:18,0:18:42:0,42,630 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,678 0/0:10,0:10:30:0,30,380 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,753 0/0:6,0:6:15:0,15,225 0/0:7,0:7:21:0,21,283 0/0:20,0:20:60:0,60,792 0/0:9,0:9:24:0,24,349 ./.:1,0:1:.:. 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,257 0/0:2,0:2:6:0,6,63 +20 17446204 rs140522302 TG T 10972.40 PASS HWP=0.0083;AC=4;culprit=MQRankSum;MQ0=0;ReadPosRankSum=0.296;AN=200;InbreedingCoeff=0.1091;AF=0.029;GQ_STDDEV=38.03;FS=3.355;DP=13882;GQ_MEAN=44.26;POSITIVE_TRAIN_SITE;VQSLOD=3.05;ClippingRankSum=0.474;BaseQRankSum=0.185;MLEAF=0.028;MLEAC=49;MQ=60.0;QD=14.34;DB;MQRankSum=0.694;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:9,0:9:24:0,24,360 0/0:8,0:8:21:0,21,315 0/0:15,0:15:36:0,36,540 0/0:18,0:18:21:0,21,630 0/0:11,0:11:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:10,0:10:30:0,30,433 0/0:22,0:22:45:0,45,675 1/1:0,13:13:40:425,40,0 0/0:13,0:13:24:0,24,360 0/0:13,0:13:33:0,33,495 0/0:13,0:13:21:0,21,315 0/0:11,0:11:20:0,20,315 0/0:12,0:12:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:12,0:12:25:0,25,434 0/0:8,0:8:21:0,21,315 0/0:20,0:20:60:0,60,825 0/0:20,0:20:60:0,60,868 0/0:18,0:18:39:0,39,585 0/0:20,0:20:60:0,60,774 0/0:22,0:22:60:0,60,870 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:12,0:12:24:0,24,360 0/0:30,0:30:60:0,60,900 0/0:29,0:29:77:0,77,1037 0/0:23,0:23:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:8,0:8:21:0,21,315 1/1:1,25:26:47:781,47,0 0/0:10,0:10:24:0,24,360 0/0:15,0:15:30:0,30,540 0/0:23,0:23:60:0,60,900 0/0:14,0:14:20:0,20,495 0/0:13,0:13:33:0,33,463 0/0:11,0:11:27:0,27,405 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:14,0:14:23:0,23,495 0/0:20,0:20:60:0,60,762 0/0:11,0:11:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:14,0:14:36:0,36,540 0/0:10,0:10:21:0,21,315 0/0:11,0:11:30:0,30,389 0/0:21,0:21:51:0,51,765 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:31,0:31:53:0,53,986 0/0:26,0:26:60:0,60,900 0/0:20,0:20:45:0,45,675 0/0:28,0:28:61:0,61,919 0/0:28,0:28:63:0,63,945 0/0:14,0:14:39:0,39,585 0/0:10,0:10:21:0,21,315 0/0:10,0:10:27:0,27,376 0/0:2,0:2:6:0,6,75 0/0:9,0:9:21:0,21,315 0/0:20,0:20:60:0,60,838 0/0:9,0:9:21:0,21,315 0/0:20,0:20:60:0,60,736 0/0:9,0:9:21:0,21,315 0/0:26,0:26:57:0,57,855 0/0:8,0:8:21:0,21,291 0/0:9,0:9:21:0,21,315 0/0:13,0:13:21:0,21,315 0/0:12,0:12:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:15,0:15:33:0,33,495 0/0:12,0:12:21:0,21,315 0/0:13,0:13:20:0,20,537 0/0:13,0:13:33:0,33,495 0/0:5,0:5:9:0,9,135 0/0:8,0:8:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:10,0:10:24:0,24,360 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,678 0/0:11,0:11:21:0,21,315 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,301 0/0:11,0:11:24:0,24,360 0/0:8,0:8:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,274 0/0:6,0:6:12:0,12,180 0/0:8,0:8:20:0,20,315 0/0:5,0:5:12:0,12,180 0/0:9,0:9:24:0,24,360 +20 17462235 . A C 6837.00 VQSRTrancheSNP99.95to100.00 HWP=0.8286;AC=13;culprit=FS;MQ0=0;ReadPosRankSum=-2.662;AN=200;InbreedingCoeff=-0.0602;AF=0.032;GQ_STDDEV=35.42;FS=245.044;DP=38291;GQ_MEAN=61.61;VQSLOD=-520.8;ClippingRankSum=2.72;BaseQRankSum=-6.199;MLEAF=0.034;MLEAC=59;MQ=59.14;QD=1.08;MQRankSum=0.507;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:35,0:35:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:115,0:115:99:0,120,1800 0/0:32,0:32:74:0,74,1215 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:100,0:100:99:0,120,1800 0/0:26,0:26:66:0,66,990 0/0:31,0:31:76:0,76,1215 0/0:29,0:29:61:0,61,1024 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:47,0:47:99:0,113,1710 0/0:44,0:44:93:0,93,1395 0/0:26,0:26:66:0,66,990 0/1:62,32:94:99:120,0,1741 0/1:85,39:124:99:146,0,2278 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:34,0:34:71:0,71,1258 0/0:141,0:141:0:0,0,3584 0/0:126,0:126:0:0,0,3019 0/0:24,0:24:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:92,0:92:0:0,0,2358 0/0:53,0:53:5:0,5,1487 0/0:65,0:65:7:0,7,1734 0/0:75,0:75:8:0,8,2012 0/0:89,0:89:0:0,0,2393 0/0:107,0:107:19:0,19,2870 0/1:76,44:120:99:166,0,2118 0/0:76,0:76:26:0,26,2046 0/0:24,0:24:61:0,61,945 0/0:94,0:94:0:0,0,2295 0/0:110,0:110:0:0,0,2492 0/0:31,0:31:78:0,78,1170 0/0:27,0:27:60:0,60,900 0/0:76,0:76:58:0,58,2201 0/0:38,0:38:84:0,84,1305 0/0:97,0:97:43:0,43,2509 0/0:28,0:28:60:0,60,900 0/0:33,0:33:84:0,84,1260 0/1:82,29:111:99:129,0,2455 0/0:94,0:94:0:0,0,2473 0/0:31,0:31:62:0,62,1195 0/0:20,0:20:60:0,60,782 0/0:70,0:70:42:0,42,1857 0/1:138,48:186:77:77,0,3857 0/0:66,0:66:0:0,0,1601 0/0:88,0:88:32:0,32,2384 0/0:39,0:39:79:0,79,1336 0/0:48,0:48:38:0,38,1393 0/0:49,0:49:0:0,0,1211 0/1:100,54:154:99:162,0,2450 0/0:59,0:59:0:0,0,1441 0/0:30,0:30:60:0,60,900 0/1:56,37:93:99:176,0,1376 0/0:24,0:24:60:0,60,900 0/0:69,0:69:0:0,0,1637 0/0:61,0:61:0:0,0,1467 0/1:54,21:75:99:131,0,1415 0/0:37,0:37:84:0,84,1260 0/0:61,0:61:2:0,2,1540 0/0:65,0:65:0:0,0,1627 0/0:65,0:65:0:0,0,1381 0/0:29,0:29:61:0,61,1035 0/0:44,0:44:0:0,0,1142 0/1:43,30:73:99:161,0,1109 0/1:88,40:128:99:148,0,2345 0/0:63,0:63:0:0,0,1512 0/0:116,0:116:15:0,15,2923 0/0:35,0:35:66:0,66,990 0/0:28,0:28:63:0,63,1125 0/0:27,0:27:61:0,61,990 0/0:127,0:127:47:0,47,3274 0/0:35,0:35:72:0,72,1080 0/0:31,0:31:60:0,60,900 0/0:81,0:81:0:0,0,1713 0/1:51,30:81:99:127,0,1347 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/1:48,20:68:70:70,0,1252 0/0:66,0:66:0:0,0,1718 0/1:44,24:68:99:113,0,1187 0/0:72,0:72:48:0,48,1940 +20 17462246 . G T 2432.31 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.95;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=58.31;FS=0.0;DP=25199;GQ_MEAN=69.3;VQSLOD=1.73;ClippingRankSum=-1.026;BaseQRankSum=-1.742;MLEAF=0.001149;MLEAC=2;MQ=59.09;QD=11.64;MQRankSum=0.573;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:35,0:35:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/1:64,48:112:99:1404,0,2008 0/0:32,0:32:74:0,74,1215 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/1:56,41:97:99:1105,0,1624 0/0:26,0:26:66:0,66,990 0/0:31,0:31:76:0,76,1215 0/0:29,0:29:61:0,61,1024 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:47,0:47:99:0,113,1710 0/0:44,0:44:93:0,93,1395 0/0:26,0:26:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:34,0:34:71:0,71,1258 0/0:38,0:38:93:0,93,1395 0/0:39,0:39:77:0,77,1200 0/0:24,0:24:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,741 0/0:33,0:33:66:0,66,990 0/0:33,0:33:72:0,72,1080 0/0:33,0:33:61:0,61,1119 0/0:36,0:36:90:0,90,1350 0/0:27,0:27:64:0,64,1035 0/0:29,0:29:67:0,67,1080 0/0:23,0:23:60:0,60,900 0/0:24,0:24:61:0,61,945 0/0:27,0:27:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:31,0:31:78:0,78,1170 0/0:27,0:27:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:38,0:38:84:0,84,1305 0/0:25,0:25:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:33,0:33:84:0,84,1260 0/0:37,0:37:83:0,83,1350 0/0:29,0:29:75:0,75,898 0/0:31,0:31:62:0,62,1195 0/0:20,0:20:60:0,60,782 0/0:28,0:28:63:0,63,945 0/0:36,0:36:81:0,81,1215 0/0:29,0:29:60:0,60,900 0/0:29,0:29:69:0,69,995 0/0:39,0:39:79:0,79,1336 0/0:31,0:31:66:0,66,990 0/0:27,0:27:69:0,69,1010 0/0:28,0:28:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:32,0:32:72:0,72,1125 0/0:27,0:27:69:0,69,970 0/0:37,0:37:84:0,84,1260 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:29,0:29:61:0,61,1035 0/0:25,0:25:66:0,66,990 0/0:26,0:26:60:0,60,881 0/0:24,0:24:60:0,60,900 0/0:31,0:31:74:0,74,1170 0/0:26,0:26:63:0,63,945 0/0:35,0:35:66:0,66,990 0/0:28,0:28:63:0,63,1125 0/0:27,0:27:61:0,61,990 0/0:31,0:31:63:0,63,945 0/0:35,0:35:72:0,72,1080 0/0:31,0:31:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:44,0:44:99:0,102,1530 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:30,0:30:63:0,63,1080 0/0:27,0:27:69:0,69,984 0/0:28,0:28:72:0,72,1080 0/0:29,0:29:63:0,63,945 +20 17462371 rs139619496 A G 326.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.215;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=14.01;FS=1.378;DP=24379;GQ_MEAN=65.84;POSITIVE_TRAIN_SITE;VQSLOD=1.42;ClippingRankSum=0.338;BaseQRankSum=1.72;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=8.6;DB;MQRankSum=-1.262;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:35,0:35:60:0,60,900 0/0:30,0:30:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:32,0:32:74:0,74,1215 0/0:21,0:21:54:0,54,810 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:31,0:31:76:0,76,1215 0/0:29,0:29:61:0,61,1024 0/0:22,0:22:60:0,60,876 0/0:27,0:27:60:0,60,900 0/0:47,0:47:99:0,113,1710 0/0:44,0:44:93:0,93,1395 0/0:26,0:26:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:34,0:34:71:0,71,1258 0/0:38,0:38:93:0,93,1395 0/0:39,0:39:77:0,77,1200 0/0:24,0:24:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,741 0/0:33,0:33:66:0,66,990 0/0:33,0:33:72:0,72,1080 0/0:33,0:33:61:0,61,1119 0/0:36,0:36:90:0,90,1350 0/0:27,0:27:64:0,64,1035 0/0:29,0:29:67:0,67,1080 0/0:23,0:23:60:0,60,900 0/0:24,0:24:61:0,61,945 0/0:27,0:27:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:31,0:31:78:0,78,1170 0/0:27,0:27:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:38,0:38:84:0,84,1305 0/0:25,0:25:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:33,0:33:84:0,84,1260 0/0:37,0:37:83:0,83,1350 0/0:29,0:29:75:0,75,898 0/0:31,0:31:62:0,62,1195 0/0:20,0:20:60:0,60,782 0/0:28,0:28:63:0,63,945 0/0:36,0:36:81:0,81,1215 0/0:29,0:29:60:0,60,900 0/0:29,0:29:69:0,69,995 0/0:39,0:39:79:0,79,1336 0/0:23,0:23:60:0,60,830 0/0:23,0:23:54:0,54,810 0/0:28,0:28:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:32,0:32:72:0,72,1125 0/0:25,0:25:63:0,63,945 0/1:25,13:38:99:377,0,789 0/0:27,0:27:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:26,0:26:60:0,60,881 0/0:24,0:24:60:0,60,900 0/0:31,0:31:74:0,74,1170 0/0:26,0:26:63:0,63,945 0/0:35,0:35:66:0,66,990 0/0:28,0:28:63:0,63,1125 0/0:27,0:27:61:0,61,990 0/0:31,0:31:63:0,63,945 0/0:35,0:35:72:0,72,1080 0/0:31,0:31:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:27,0:27:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:27,0:27:69:0,69,984 0/0:23,0:23:60:0,60,900 0/0:29,0:29:63:0,63,945 +20 17474690 rs6105762 T G 1168990.00 PASS HWP=0.7462;AC=104;culprit=FS;MQ0=0;ReadPosRankSum=0.442;AN=200;InbreedingCoeff=0.0099;AF=0.517;GQ_STDDEV=657.44;FS=0.0;DP=56293;GQ_MEAN=581.87;POSITIVE_TRAIN_SITE;VQSLOD=6.63;ClippingRankSum=-0.256;BaseQRankSum=5.18;MLEAF=0.518;MLEAC=901;MQ=59.75;QD=25.22;DB;MQRankSum=0.155;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:40,0:40:99:0,117,1435 0/0:34,0:34:99:0,102,1252 1/1:2,43:45:97:1686,97,0 1/1:0,39:39:99:1593,117,0 1/1:1,66:67:99:2673,198,0 0/0:49,0:49:99:0,117,1800 0/0:32,0:32:96:0,96,1142 0/0:58,0:58:91:0,91,1800 1/1:0,52:52:99:2062,156,0 1/1:0,61:61:99:2598,184,0 1/1:1,53:54:99:2119,160,0 0/1:43,37:80:99:1346,0,1311 0/1:28,21:49:99:701,0,857 1/1:0,50:50:99:1881,150,0 0/1:28,32:60:99:1050,0,867 0/1:33,30:63:99:992,0,1028 0/1:37,42:79:99:1413,0,1175 0/1:29,26:55:99:865,0,924 1/1:1,88:89:99:3426,229,0 0/1:30,26:56:99:848,0,956 0/1:26,28:54:99:951,0,820 0/1:38,37:75:99:1258,0,1227 0/1:33,29:62:99:1037,0,1117 0/0:29,0:29:66:0,66,990 0/1:47,38:85:99:1281,0,1455 0/1:55,70:125:99:2423,0,1668 0/0:51,0:51:99:0,114,1710 0/1:28,36:64:99:1351,0,759 0/0:55,0:55:99:0,120,1800 0/0:38,0:38:99:0,108,1620 1/1:0,39:39:99:1698,117,0 0/1:81,73:154:99:2622,0,2406 1/1:0,187:187:99:7974,561,0 1/1:0,141:141:99:6000,424,0 0/1:16,19:35:99:692,0,474 1/1:0,29:29:87:1188,87,0 0/1:36,31:67:99:1024,0,1162 0/1:54,37:91:99:1209,0,1735 0/1:74,63:137:99:2156,0,2299 1/1:0,90:90:99:3618,270,0 0/1:46,46:92:99:1569,0,1391 1/1:0,93:93:99:3723,280,0 0/0:73,0:73:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/1:49,57:106:99:2015,0,1477 0/1:75,59:134:99:1987,0,2315 0/1:60,48:108:99:1746,0,1942 1/1:0,94:94:99:3955,283,0 0/1:48,30:78:99:961,0,1493 0/1:51,50:101:99:1711,0,1579 1/1:0,76:76:99:2991,229,0 0/1:42,45:87:99:1652,0,1248 0/0:94,0:94:99:0,120,1800 1/1:0,105:105:99:4211,316,0 0/1:83,47:130:99:1514,0,2696 1/1:0,119:119:99:4825,357,0 0/1:72,68:140:99:2341,0,2199 0/1:58,60:118:99:2266,0,1801 0/1:54,59:113:99:2082,0,1662 0/0:92,0:92:99:0,120,1800 0/1:99,93:192:99:3431,0,2984 0/1:63,58:121:99:1977,0,1916 0/0:72,0:72:99:0,120,1800 0/1:42,45:87:99:1519,0,1313 0/1:29,34:63:99:1275,0,878 1/1:0,63:63:99:2742,190,0 0/1:70,59:129:99:2152,0,2196 0/0:29,0:29:68:0,68,1050 1/1:0,160:160:99:6867,482,0 0/1:48,46:94:99:1719,0,1492 1/1:0,132:132:99:5707,397,0 0/0:63,0:63:99:0,120,1800 1/1:0,111:111:99:4803,334,0 0/1:44,34:78:99:1243,0,1373 1/1:0,110:110:99:4681,331,0 0/1:49,46:95:99:1690,0,1475 0/0:62,0:62:99:0,120,1800 1/1:0,95:95:99:4129,286,0 0/0:32,0:32:84:0,84,1155 0/1:37,33:70:99:1248,0,1112 0/1:34,31:65:99:1124,0,1057 0/0:71,0:71:99:0,120,1800 1/1:0,102:102:99:4428,307,0 0/1:83,64:147:99:2299,0,2558 0/0:22,0:22:66:0,66,803 0/0:31,0:31:93:0,93,1334 0/1:26,33:59:99:1147,0,810 0/1:77,70:147:99:2586,0,2328 0/1:12,16:28:99:582,0,378 0/1:19,20:39:99:733,0,548 1/1:0,74:74:99:3191,223,0 1/1:0,56:56:99:2385,169,0 0/1:14,12:26:99:417,0,436 0/0:21,0:21:60:0,60,900 0/1:35,37:72:99:1397,0,1050 0/1:40,41:81:99:1508,0,1224 0/1:44,39:83:99:1434,0,1363 1/1:0,109:109:99:4699,328,0 +20 17474710 rs41276390 C G 154008.00 PASS HWP=0.0;AC=6;culprit=FS;MQ0=0;ReadPosRankSum=0.311;AN=200;InbreedingCoeff=0.2302;AF=0.066;GQ_STDDEV=417.45;FS=0.0;DP=60700;GQ_MEAN=222.43;POSITIVE_TRAIN_SITE;VQSLOD=5.37;ClippingRankSum=-0.646;BaseQRankSum=-5.719;MLEAF=0.066;MLEAC=114;MQ=59.78;QD=16.34;DB;MQRankSum=0.291;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:40,0:40:99:0,117,1435 0/0:34,0:34:99:0,102,1252 0/0:47,0:47:99:0,120,1800 0/0:43,0:43:96:0,96,1605 0/0:69,0:69:99:0,120,1800 0/0:49,0:49:99:0,117,1800 0/0:32,0:32:96:0,96,1142 0/0:58,0:58:91:0,91,1800 0/0:54,0:54:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:53,0:53:99:0,120,1800 1/1:0,61:61:99:1899,182,0 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:87,0:87:99:0,120,1800 0/0:126,0:126:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:67,0:67:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:38,0:38:99:0,108,1620 0/0:39,0:39:83:0,83,1620 0/0:154,0:154:99:0,120,1800 0/0:190,0:190:99:0,120,1800 0/0:148,0:148:99:0,120,1800 0/0:35,0:35:96:0,96,1440 1/1:1,46:47:99:1564,99,0 0/0:69,0:69:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:140,0:140:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:141,0:141:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/1:73,67:140:99:1745,0,2435 0/0:79,0:79:99:0,120,1800 0/1:58,62:120:99:1820,0,2068 0/0:94,0:94:99:0,120,1800 0/0:111,0:111:99:0,120,1800 0/0:134,0:134:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:146,0:146:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:196,0:196:99:0,120,1800 0/0:122,0:122:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:134,0:134:99:0,120,1800 0/0:29,0:29:68:0,68,1050 0/0:162,0:162:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:137,0:137:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:32,0:32:84:0,84,1155 0/0:71,0:71:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:154,0:154:99:0,120,1800 0/0:22,0:22:66:0,66,803 0/0:31,0:31:93:0,93,1334 0/0:61,0:61:99:0,120,1800 0/0:151,0:151:99:0,120,1800 0/0:28,0:28:84:0,84,1045 0/0:41,0:41:99:0,117,1755 0/0:78,0:78:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:28,0:28:76:0,76,1015 0/0:21,0:21:60:0,60,900 0/0:74,0:74:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:110,0:110:99:0,120,1800 +20 17474749 rs16999317 G T 91440.10 PASS HWP=0.1558;AC=2;culprit=ReadPosRankSum;MQ0=0;ReadPosRankSum=0.073;AN=200;InbreedingCoeff=0.0758;AF=0.024;GQ_STDDEV=434.58;FS=1.249;DP=64890;GQ_MEAN=192.35;POSITIVE_TRAIN_SITE;VQSLOD=5.89;ClippingRankSum=0.238;BaseQRankSum=-3.181;MLEAF=0.024;MLEAC=41;MQ=59.63;QD=13.92;DB;MQRankSum=0.187;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:40,0:40:99:0,117,1435 0/0:34,0:34:99:0,102,1252 0/0:47,0:47:99:0,120,1800 0/0:43,0:43:96:0,96,1605 0/0:69,0:69:99:0,120,1800 0/0:49,0:49:99:0,117,1800 0/0:32,0:32:96:0,96,1142 0/0:58,0:58:91:0,91,1800 0/0:54,0:54:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/1:94,68:162:99:1864,0,2724 0/0:56,0:56:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/1:107,106:213:99:2988,0,3326 0/0:126,0:126:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:67,0:67:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:38,0:38:99:0,108,1620 0/0:39,0:39:83:0,83,1620 0/0:154,0:154:99:0,120,1800 0/0:190,0:190:99:0,120,1800 0/0:148,0:148:99:0,120,1800 0/0:35,0:35:96:0,96,1440 0/0:49,0:49:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:140,0:140:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:141,0:141:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:143,0:143:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:122,0:122:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:111,0:111:99:0,120,1800 0/0:134,0:134:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:146,0:146:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:196,0:196:99:0,120,1800 0/0:122,0:122:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:134,0:134:99:0,120,1800 0/0:29,0:29:68:0,68,1050 0/0:162,0:162:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:137,0:137:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:32,0:32:84:0,84,1155 0/0:71,0:71:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:154,0:154:99:0,120,1800 0/0:22,0:22:66:0,66,803 0/0:31,0:31:93:0,93,1334 0/0:61,0:61:99:0,120,1800 0/0:151,0:151:99:0,120,1800 0/0:28,0:28:84:0,84,1045 0/0:41,0:41:99:0,117,1755 0/0:78,0:78:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:28,0:28:76:0,76,1015 0/0:21,0:21:60:0,60,900 0/0:74,0:74:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:110,0:110:99:0,120,1800 +20 17474791 rs6080717 G A 1014230.00 PASS HWP=0.1801;AC=41;culprit=FS;MQ0=0;ReadPosRankSum=0.585;AN=200;InbreedingCoeff=0.0485;AF=0.217;GQ_STDDEV=1271.93;FS=0.0;DP=100966;GQ_MEAN=908.76;POSITIVE_TRAIN_SITE;VQSLOD=7.04;ClippingRankSum=-0.339;BaseQRankSum=1.38;MLEAF=0.217;MLEAC=377;MQ=59.63;QD=15.97;DB;MQRankSum=0.254;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:40,0:40:99:0,117,1435 0/0:34,0:34:99:0,102,1252 0/1:106,83:189:99:2301,0,2750 0/0:43,0:43:96:0,96,1605 0/0:69,0:69:99:0,120,1800 0/0:49,0:49:99:0,117,1800 0/0:32,0:32:96:0,96,1142 0/0:58,0:58:91:0,91,1800 0/1:97,70:167:99:1975,0,2601 0/0:61,0:61:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:53,0:53:99:0,120,1800 1/1:0,111:111:99:3893,334,0 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/1:108,82:190:99:2320,0,3000 0/1:128,134:262:99:3787,0,3529 0/0:90,0:90:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/1:161,186:347:99:5035,0,4392 0/0:29,0:29:66:0,66,990 0/0:153,0:153:99:0,120,1800 0/1:138,120:258:99:3710,0,3762 0/0:51,0:51:99:0,114,1710 0/0:67,0:67:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:38,0:38:99:0,108,1620 0/1:90,76:166:99:2096,0,2517 0/0:154,0:154:99:0,120,1800 0/1:195,151:346:99:4322,0,5889 0/0:148,0:148:99:0,120,1800 0/0:35,0:35:96:0,96,1440 1/1:1,150:151:99:4860,450,0 0/0:69,0:69:99:0,120,1800 0/1:85,127:212:99:3663,0,2394 0/0:140,0:140:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/1:95,92:187:99:2818,0,2647 0/1:134,102:236:99:3028,0,3803 0/0:73,0:73:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/1:134,94:228:99:2786,0,3910 0/0:141,0:141:99:0,120,1800 0/1:173,131:304:99:3820,0,5302 1/1:1,281:282:99:10047,844,0 0/1:113,98:211:99:3005,0,3221 0/1:108,134:242:99:4031,0,3056 1/1:0,174:174:99:6284,523,0 0/1:169,132:301:99:3756,0,4798 0/0:94,0:94:99:0,120,1800 1/1:0,223:223:99:7695,670,0 0/1:156,114:270:99:3470,0,4484 0/0:119,0:119:99:0,120,1800 0/0:146,0:146:99:0,120,1800 0/1:167,159:326:99:4917,0,5208 0/0:115,0:115:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/1:175,153:328:99:4528,0,5401 0/0:122,0:122:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/1:122,103:225:99:2991,0,3388 0/1:102,94:196:99:2817,0,3046 0/1:72,84:156:99:2526,0,2181 0/1:159,143:302:99:4285,0,4678 0/0:29,0:29:68:0,68,1050 0/1:178,133:311:99:3986,0,5100 0/0:97,0:97:99:0,120,1800 0/1:180,158:338:99:4503,0,4981 0/0:63,0:63:99:0,120,1800 0/1:137,115:252:99:3449,0,4062 0/0:78,0:78:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/1:142,116:258:99:3360,0,4373 0/0:62,0:62:99:0,120,1800 0/1:153,174:327:99:4952,0,4428 0/0:32,0:32:84:0,84,1155 0/1:94,101:195:99:2850,0,2732 0/0:67,0:67:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:154,0:154:99:0,120,1800 0/0:22,0:22:66:0,66,803 0/0:31,0:31:93:0,93,1334 0/0:61,0:61:99:0,120,1800 0/0:151,0:151:99:0,120,1800 0/1:95,92:187:99:2480,0,2436 0/0:41,0:41:99:0,117,1755 0/1:123,130:253:99:3772,0,3537 0/0:58,0:58:99:0,120,1800 0/0:28,0:28:76:0,76,1015 0/0:21,0:21:60:0,60,900 0/0:74,0:74:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:110,0:110:99:0,120,1800 +20 17474833 rs181266441 G A 1326.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.108;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=46.51;FS=2.451;DP=81120;GQ_MEAN=113.13;VQSLOD=2.8;ClippingRankSum=0.003;BaseQRankSum=-0.633;MLEAF=5.747E-4;MLEAC=1;MQ=59.67;QD=11.85;DB;MQRankSum=-1.351;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:40,0:40:99:0,117,1435 0/0:34,0:34:99:0,102,1252 0/0:132,0:132:99:0,120,1800 0/0:43,0:43:96:0,96,1605 0/0:69,0:69:99:0,120,1800 0/0:49,0:49:99:0,117,1800 0/0:32,0:32:96:0,96,1142 0/0:58,0:58:91:0,91,1800 0/0:148,0:148:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:107,0:107:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:176,0:176:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:153,0:153:99:0,120,1800 0/0:161,0:161:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:67,0:67:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:38,0:38:99:0,108,1620 0/0:138,0:138:99:0,120,1800 0/0:154,0:154:99:0,120,1800 0/0:241,0:241:99:0,120,1800 0/0:148,0:148:99:0,120,1800 0/0:35,0:35:96:0,96,1440 0/0:91,0:91:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:125,0:125:99:0,120,1800 0/0:140,0:140:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:123,0:123:99:0,120,1800 0/0:139,0:139:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:158,0:158:99:0,120,1800 0/0:141,0:141:99:0,120,1800 0/0:177,0:177:99:0,120,1800 0/0:207,0:207:99:0,120,1800 0/0:163,0:163:99:0,120,1800 0/0:139,0:139:99:0,120,1800 0/0:117,0:117:99:0,120,1800 0/0:131,0:131:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:133,0:133:99:0,120,1800 0/0:200,0:200:99:0,120,1800 0/0:119,0:119:99:0,120,1800 0/0:146,0:146:99:0,120,1800 0/0:189,0:189:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:256,0:256:99:0,120,1800 0/0:122,0:122:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:215,0:215:99:0,120,1800 0/0:29,0:29:68:0,68,1050 0/0:184,0:184:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:183,0:183:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:116,0:116:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:128,0:128:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:140,0:140:99:0,120,1800 0/0:32,0:32:84:0,84,1155 0/0:72,0:72:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:104,0:104:99:0,120,1800 0/0:154,0:154:99:0,120,1800 0/0:22,0:22:66:0,66,803 0/1:60,52:112:99:1377,0,1632 0/0:61,0:61:99:0,120,1800 0/0:151,0:151:99:0,120,1800 0/0:126,0:126:99:0,120,1800 0/0:41,0:41:99:0,117,1755 0/0:111,0:111:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:28,0:28:76:0,76,1015 0/0:21,0:21:60:0,60,900 0/0:74,0:74:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:110,0:110:99:0,120,1800 +20 17474968 . T C 3792830.00 PASS HWP=0.9536;AC=151;culprit=FS;MQ0=0;ReadPosRankSum=0.271;AN=200;InbreedingCoeff=0.0167;AF=0.78;GQ_STDDEV=968.94;FS=0.0;DP=143880;GQ_MEAN=1090.27;POSITIVE_TRAIN_SITE;VQSLOD=4.96;ClippingRankSum=-0.082;BaseQRankSum=0.908;MLEAF=0.78;MLEAC=1357;MQ=59.63;QD=26.77;DB;MQRankSum=0.185;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,192:192:99:6449,576,0 1/1:3,179:182:99:6133,536,0 0/1:97,85:182:99:2581,0,2665 1/1:4,199:203:99:6828,597,0 1/1:1,188:189:99:6614,562,0 1/1:5,227:232:99:7873,682,0 1/1:6,214:220:99:7721,643,0 1/1:3,145:148:99:5132,436,0 0/1:82,96:178:99:2705,0,2406 1/1:0,222:222:99:7775,667,0 1/1:0,196:196:99:7173,589,0 1/1:0,166:166:99:5929,498,0 0/1:123,97:220:99:2867,0,3570 0/1:99,93:192:99:2718,0,2810 1/1:0,74:74:99:2497,223,0 0/1:53,60:113:99:1767,0,1563 1/1:0,113:113:99:3817,340,0 0/1:55,41:96:99:1137,0,1652 0/1:60,43:103:99:1193,0,1669 1/1:0,146:146:99:5108,439,0 0/1:44,61:105:99:1805,0,1201 0/1:49,57:106:99:1599,0,1388 1/1:0,113:113:99:3912,339,0 0/1:115,89:204:99:2518,0,3401 0/0:29,0:29:66:0,66,990 0/1:83,77:160:99:1981,0,2418 0/1:97,96:193:99:2547,0,2762 0/0:51,0:51:99:0,114,1710 1/1:0,198:198:99:6998,595,0 1/1:0,215:215:99:7451,646,0 0/1:81,82:163:99:2350,0,2211 1/1:0,181:181:99:6323,544,0 0/1:104,115:219:99:3152,0,2933 1/1:0,260:260:99:9230,780,0 1/1:0,223:223:99:7578,666,0 1/1:0,112:112:99:3776,336,0 1/1:2,163:165:99:5696,462,0 1/1:0,97:97:99:3354,292,0 1/1:0,163:163:99:5394,487,0 1/1:0,186:186:99:6119,557,0 1/1:0,160:160:99:5408,481,0 1/1:0,129:129:99:4301,388,0 1/1:0,165:165:99:5628,495,0 1/1:0,173:173:99:5872,519,0 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/1:99,81:180:99:2224,0,2854 0/1:101,85:186:99:2265,0,2873 1/1:0,207:207:99:7399,622,0 1/1:0,223:223:99:7870,669,0 1/1:0,195:195:99:6532,585,0 0/1:88,79:167:99:2034,0,2466 1/1:0,121:121:99:3987,363,0 1/1:1,147:148:99:5127,407,0 0/1:93,82:175:99:2418,0,2728 1/1:0,153:153:99:4867,458,0 0/1:104,108:212:99:2910,0,2998 1/1:1,195:196:99:6490,554,0 0/1:114,98:212:99:2715,0,3198 1/1:0,216:216:99:7823,648,0 1/1:0,143:143:99:4817,430,0 0/1:102,93:195:99:2443,0,2970 1/1:0,278:278:99:9957,834,0 0/1:116,79:195:99:2122,0,3332 1/1:0,164:164:99:5460,493,0 0/1:65,76:141:99:2229,0,1921 1/1:0,102:102:99:3658,306,0 1/1:0,96:96:99:3262,288,0 0/1:106,127:233:99:3768,0,3054 0/0:29,0:29:68:0,68,1050 1/1:0,196:196:99:6929,588,0 1/1:1,156:157:99:5603,434,0 1/1:1,190:191:99:6628,561,0 0/1:83,64:147:99:1846,0,2422 1/1:0,150:150:99:5475,451,0 0/1:71,54:125:99:1590,0,2048 1/1:0,171:171:99:6182,513,0 0/1:76,71:147:99:2122,0,2276 0/1:91,94:185:99:2762,0,2561 1/1:0,158:158:99:5741,474,0 0/0:32,0:32:84:0,84,1155 0/1:38,38:76:99:1138,0,1118 1/1:0,97:97:99:3450,291,0 0/1:82,82:164:99:2531,0,2348 1/1:0,166:166:99:5982,498,0 0/1:104,93:197:99:2670,0,2939 1/1:0,191:191:99:6240,572,0 0/0:31,0:31:60:0,60,900 0/1:62,58:120:99:1648,0,1694 1/1:0,255:255:99:9094,766,0 1/1:1,198:199:99:6610,591,0 1/1:0,194:194:99:6669,583,0 1/1:0,140:140:99:5002,421,0 1/1:0,121:121:99:4470,364,0 0/1:96,101:197:99:2783,0,2732 0/1:79,54:133:99:1589,0,2015 1/1:0,128:128:99:4583,384,0 0/1:55,56:111:99:1669,0,1571 1/1:0,108:108:99:3843,324,0 1/1:2,169:171:99:5903,462,0 +20 17475115 rs185730111 T C 996.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.289;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=37.13;FS=2.919;DP=43777;GQ_MEAN=99.14;POSITIVE_TRAIN_SITE;VQSLOD=3.95;ClippingRankSum=-0.852;BaseQRankSum=4.44;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=16.08;DB;MQRankSum=0.247;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:52,0:52:99:0,120,1800 0/0:46,0:46:99:0,111,1665 0/0:75,0:75:99:0,120,1800 0/0:30,0:30:75:0,75,1125 0/0:25,0:25:60:0,60,900 0/0:34,0:34:78:0,78,1170 0/0:46,0:46:99:0,105,1575 0/0:49,0:49:99:0,117,1755 0/0:48,0:48:99:0,102,1530 0/0:68,0:68:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:41,0:41:99:0,102,1530 0/0:46,0:46:99:0,103,1755 0/0:44,0:44:99:0,105,1644 0/0:50,0:50:99:0,120,1800 0/0:37,0:37:92:0,92,1254 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,107,1675 0/0:41,0:41:86:0,86,1457 0/0:49,0:49:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:62,0:62:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:57,0:57:99:0,120,1800 0/0:49,0:49:99:0,114,1710 0/0:45,0:45:99:0,111,1665 0/0:27,0:27:60:0,60,900 0/0:92,0:92:99:0,120,1800 0/0:114,0:114:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:41,0:41:99:0,102,1530 0/0:41,0:41:99:0,102,1530 0/0:47,0:47:99:0,103,1575 0/0:76,0:76:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:48,0:48:99:0,111,1665 0/0:57,0:57:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:55,0:55:99:0,110,1800 0/0:41,0:41:83:0,83,1398 0/0:39,0:39:90:0,90,1350 0/0:53,0:53:99:0,114,1710 0/0:46,0:46:99:0,114,1710 0/0:94,0:94:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:45,0:45:94:0,94,1620 0/0:26,0:26:60:0,60,900 0/0:34,0:34:75:0,75,1125 0/0:61,0:61:99:0,120,1800 0/0:29,0:29:68:0,68,1050 0/0:51,0:51:99:0,120,1800 0/0:38,0:38:93:0,93,1395 0/0:57,0:57:99:0,120,1800 0/0:32,0:32:76:0,76,1075 0/0:40,0:40:90:0,90,1350 0/0:30,0:30:63:0,63,945 0/0:31,0:31:84:0,84,1260 0/0:41,0:41:99:0,102,1530 0/1:32,30:62:99:1047,0,934 0/0:43,0:43:99:0,102,1530 0/0:32,0:32:84:0,84,1155 0/0:28,0:28:66:0,66,990 0/0:26,0:26:66:0,66,990 0/0:40,0:40:99:0,99,1485 0/0:46,0:46:98:0,98,1620 0/0:65,0:65:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:31,0:31:60:0,60,900 0/0:48,0:48:99:0,102,1694 0/0:105,0:105:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:50,0:50:99:0,120,1800 0/0:36,0:36:93:0,93,1395 0/0:32,0:32:75:0,75,1125 0/0:54,0:54:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:33,0:33:81:0,81,1215 0/0:34,0:34:90:0,90,1251 0/0:28,0:28:72:0,72,1080 0/0:42,0:42:77:0,77,1575 +20 17475217 rs6136118 C T 542850.00 PASS HWP=0.1864;AC=67;culprit=FS;MQ0=0;ReadPosRankSum=0.427;AN=200;InbreedingCoeff=0.0468;AF=0.345;GQ_STDDEV=399.59;FS=0.0;DP=47127;GQ_MEAN=395.68;POSITIVE_TRAIN_SITE;VQSLOD=6.33;ClippingRankSum=-0.241;BaseQRankSum=0.743;MLEAF=0.345;MLEAC=601;MQ=59.58;QD=17.96;DB;MQRankSum=0.147;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/1:28,26:54:99:714,0,820 1/1:1,44:45:98:1522,98,0 1/1:2,75:77:99:2701,226,0 0/0:30,0:30:75:0,75,1125 0/0:25,0:25:60:0,60,900 0/0:34,0:34:78:0,78,1170 0/1:27,19:46:99:539,0,727 1/1:1,56:57:99:1953,165,0 1/1:2,50:52:99:1531,115,0 0/1:37,31:68:99:912,0,1125 0/1:38,31:69:99:974,0,1041 1/1:0,54:54:99:1788,162,0 0/1:40,18:58:99:489,0,1156 0/1:37,20:57:99:559,0,1055 0/1:30,22:52:99:606,0,804 0/0:37,0:37:92:0,92,1254 0/0:49,0:49:99:0,120,1800 0/1:24,28:52:99:810,0,587 0/1:24,17:41:99:495,0,677 0/1:31,39:70:99:1124,0,868 0/0:27,0:27:63:0,63,945 0/0:29,0:29:66:0,66,990 0/1:39,30:69:99:884,0,1099 0/0:66,0:66:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/1:39,27:66:99:811,0,1114 0/0:49,0:49:99:0,114,1710 0/0:45,0:45:99:0,111,1665 0/0:27,0:27:60:0,60,900 0/1:46,48:94:99:1444,0,1343 0/1:61,52:113:99:1522,0,1934 1/1:0,101:101:99:3613,303,0 0/1:38,25:63:99:726,0,1007 1/1:1,52:53:99:1634,115,0 0/1:22,20:42:99:542,0,663 0/0:47,0:47:99:0,103,1575 0/1:44,43:87:99:1307,0,1172 1/1:0,59:59:99:2175,177,0 0/0:48,0:48:99:0,111,1665 0/1:44,33:77:99:1010,0,1316 0/0:72,0:72:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/1:33,41:74:99:1313,0,825 0/0:63,0:63:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/1:33,23:56:99:671,0,939 0/0:41,0:41:83:0,83,1398 0/1:21,22:43:99:661,0,594 0/0:53,0:53:99:0,114,1710 0/0:46,0:46:99:0,114,1710 0/0:94,0:94:99:0,120,1800 1/1:0,78:78:99:2877,234,0 0/1:45,26:71:99:719,0,1375 0/0:70,0:70:99:0,120,1800 0/1:32,33:65:99:1003,0,938 0/0:60,0:60:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/1:41,24:65:99:692,0,1275 0/0:58,0:58:99:0,120,1800 0/0:45,0:45:94:0,94,1620 0/0:26,0:26:60:0,60,900 0/1:15,13:28:99:388,0,447 0/0:61,0:61:99:0,120,1800 0/0:29,0:29:65:0,65,1080 0/1:35,29:64:99:919,0,973 0/1:30,30:60:99:942,0,911 0/1:43,29:72:99:814,0,1311 0/0:32,0:32:76:0,76,1075 0/1:26,21:47:99:599,0,762 0/1:24,12:36:99:324,0,636 1/1:0,40:40:99:1320,120,0 0/0:41,0:41:99:0,102,1530 0/0:43,0:43:96:0,96,1440 0/1:21,22:43:99:696,0,600 0/0:34,0:34:53:0,53,1074 0/0:26,0:26:66:0,66,990 0/1:17,21:38:99:665,0,517 0/0:40,0:40:99:0,99,1485 1/1:0,47:47:99:1733,141,0 0/1:39,37:76:99:1077,0,1226 0/0:33,0:33:75:0,75,1125 0/0:31,0:31:60:0,60,900 0/1:36,17:53:99:435,0,985 0/1:58,49:107:99:1378,0,1831 0/0:26,0:26:60:0,60,900 0/1:30,22:52:99:613,0,811 0/1:26,15:41:99:389,0,853 1/1:0,36:36:99:1283,108,0 0/1:42,27:69:99:737,0,1191 0/0:27,0:27:63:0,63,945 0/1:18,16:34:99:488,0,573 0/1:34,20:54:99:524,0,1097 0/1:16,14:30:99:403,0,523 1/1:0,45:45:99:1640,134,0 +20 17475385 . T C 24497.60 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.6;AN=200;InbreedingCoeff=-0.0087;AF=0.008621;GQ_STDDEV=205.31;FS=2.459;DP=39697;GQ_MEAN=113.69;POSITIVE_TRAIN_SITE;VQSLOD=4.05;ClippingRankSum=-0.517;BaseQRankSum=3.53;MLEAF=0.008621;MLEAC=15;MQ=59.49;QD=12.94;MQRankSum=-0.095;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:32,0:32:63:0,63,945 0/0:37,0:37:96:0,96,1440 0/0:28,0:28:72:0,72,1080 0/0:30,0:30:75:0,75,1125 0/0:25,0:25:60:0,60,900 0/0:34,0:34:78:0,78,1170 0/0:31,0:31:66:0,66,990 0/0:32,0:32:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:43,0:43:87:0,87,1305 0/0:30,0:30:78:0,78,1170 0/0:42,0:42:99:0,105,1353 0/0:38,0:38:93:0,93,1395 0/0:51,0:51:99:0,120,1800 0/0:38,0:38:96:0,96,1440 0/0:37,0:37:92:0,92,1254 0/0:49,0:49:99:0,120,1800 0/0:47,0:47:88:0,88,1530 0/0:40,0:40:99:0,100,1342 0/0:57,0:57:99:0,120,1800 0/0:27,0:27:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:63,0:63:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:51,0:51:99:0,114,1710 0/0:58,0:58:99:0,108,1800 0/0:49,0:49:99:0,114,1710 0/0:45,0:45:99:0,111,1665 0/0:27,0:27:60:0,60,900 0/0:78,0:78:99:0,120,1800 0/0:101,0:101:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:29,0:29:66:0,66,990 0/0:43,0:43:99:0,105,1575 0/0:41,0:41:93:0,93,1534 0/0:47,0:47:99:0,103,1575 0/0:83,0:83:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/0:48,0:48:99:0,111,1665 0/0:58,0:58:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:48,0:48:99:0,114,1710 0/0:54,0:54:99:0,120,1800 0/0:41,0:41:83:0,83,1398 0/0:41,0:41:93:0,93,1395 0/0:53,0:53:99:0,114,1710 0/0:46,0:46:99:0,114,1710 0/0:94,0:94:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:45,0:45:94:0,94,1620 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:61,0:61:99:0,120,1800 0/0:29,0:29:65:0,65,1080 0/0:61,0:61:99:0,120,1800 0/0:42,0:42:87:0,87,1305 0/0:69,0:69:99:0,120,1800 0/0:32,0:32:76:0,76,1075 0/0:29,0:29:66:0,66,990 0/0:35,0:35:72:0,72,1080 0/0:34,0:34:77:0,77,1170 0/0:41,0:41:99:0,102,1530 0/0:43,0:43:96:0,96,1440 0/0:41,0:41:99:0,102,1530 0/0:27,0:27:64:0,64,990 0/0:26,0:26:66:0,66,990 0/0:33,0:33:85:0,85,1155 0/0:40,0:40:99:0,99,1485 0/0:41,0:41:99:0,99,1485 0/0:65,0:65:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:31,0:31:60:0,60,900 0/0:42,0:42:73:0,73,1513 0/0:86,0:86:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:27,0:27:63:0,63,945 0/1:76,67:143:99:2138,0,2134 0/0:32,0:32:75:0,75,1125 0/0:26,0:26:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:44,0:44:99:0,102,1530 0/0:32,0:32:63:0,63,1032 0/0:43,0:43:90:0,90,1350 +20 17477592 rs6080719 C T 12606.00 PASS HWP=0.0;AC=20;culprit=MQ;MQ0=0;ReadPosRankSum=0.727;AN=126;InbreedingCoeff=0.201;AF=0.122;GQ_STDDEV=18.58;FS=2.667;DP=2627;GQ_MEAN=12.64;POSITIVE_TRAIN_SITE;VQSLOD=3.95;ClippingRankSum=0.0;BaseQRankSum=0.198;MLEAF=0.144;MLEAC=187;MQ=60.0;QD=20.97;DB;MQRankSum=0.727;CCC=1298;NCC=221 GT:AD:DP:GQ:PL 0/0:7,0:7:21:0,21,233 0/0:2,0:2:6:0,6,49 ./.:0,0:0:.:. ./.:2,0:2:.:. 1/1:0,3:3:9:119,9,0 ./.:2,0:2:.:. 0/0:2,0:2:6:0,6,61 0/0:2,0:2:6:0,6,73 0/0:7,0:7:21:0,21,256 ./.:0,0:0:.:. 1/1:0,4:4:12:129,12,0 ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:2,0:2:.:. 0/0:2,0:2:6:0,6,60 1/1:0,5:5:15:197,15,0 0/0:2,0:2:6:0,6,73 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,72 0/0:3,0:3:9:0,9,105 ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,41 0/0:7,0:7:21:0,21,294 0/0:2,0:2:6:0,6,68 0/0:7,0:7:21:0,21,224 0/0:2,0:2:6:0,6,76 ./.:4,0:4:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,63 0/0:2,0:2:6:0,6,41 0/1:3,4:7:64:138,0,64 0/1:6,3:9:92:92,0,176 ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. 0/0:7,0:7:21:0,21,241 0/1:3,3:6:94:102,0,94 1/1:0,4:4:12:159,12,0 0/0:2,0:2:6:0,6,64 0/1:1,3:4:29:106,0,29 0/0:9,0:9:21:0,21,315 0/0:2,0:2:6:0,6,58 0/0:4,0:4:6:0,6,90 ./.:1,0:1:.:. 0/1:4,4:8:99:121,0,128 0/0:2,0:2:6:0,6,61 0/0:7,0:7:21:0,21,230 0/0:3,0:3:9:0,9,91 0/0:2,0:2:6:0,6,71 0/0:3,0:3:6:0,6,83 0/0:3,0:3:9:0,9,115 0/0:5,0:5:12:0,12,145 0/0:3,0:3:9:0,9,73 0/0:7,0:7:21:0,21,256 1/1:0,8:8:24:284,24,0 ./.:1,0:1:.:. 0/0:2,0:2:6:0,6,49 0/0:2,0:2:6:0,6,62 0/0:2,0:2:6:0,6,63 0/0:13,0:13:0:0,0,373 0/0:8,0:8:0:0,0,188 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,71 0/0:2,0:2:6:0,6,74 0/1:1,4:5:29:109,0,29 0/0:7,0:7:21:0,21,247 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:4,0:4:.:. ./.:4,0:4:.:. 0/0:2,0:2:6:0,6,74 ./.:3,0:3:.:. ./.:0,0:0:.:. ./.:1,0:1:.:. 0/0:2,0:2:6:0,6,74 0/0:2,0:2:6:0,6,75 0/0:3,0:3:6:0,6,79 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,72 1/1:0,4:4:12:131,12,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:3,0:3:.:. 0/0:3,0:3:6:0,6,88 0/0:2,0:2:6:0,6,69 ./.:1,0:1:.:. 0/1:4,3:7:99:100,0,148 0/0:2,0:2:6:0,6,67 ./.:0,0:0:.:. 0/1:2,4:6:56:81,0,56 ./.:0,0:0:.:. 0/0:8,0:8:0:0,0,150 ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 17479421 . T G 471.84 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=0.023;AN=200;InbreedingCoeff=-0.0076;AF=5.747E-4;GQ_STDDEV=19.23;FS=0.0;DP=10362;GQ_MEAN=31.01;VQSLOD=1.75;ClippingRankSum=-0.209;BaseQRankSum=2.34;MLEAF=5.747E-4;MLEAC=1;MQ=58.5;QD=16.85;MQRankSum=-0.023;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:16,0:16:45:0,45,675 0/0:7,0:7:21:0,21,259 0/0:12,0:12:36:0,36,435 0/0:10,0:10:27:0,27,371 0/0:8,0:8:24:0,24,295 0/0:14,0:14:42:0,42,487 0/0:15,0:15:45:0,45,558 0/0:4,0:4:12:0,12,142 0/0:20,0:20:60:0,60,781 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,245 0/0:8,0:8:24:0,24,261 0/0:12,0:12:36:0,36,423 0/0:8,0:8:21:0,21,255 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,261 0/0:6,0:6:9:0,9,135 0/0:7,0:7:21:0,21,251 0/0:8,0:8:24:0,24,283 0/0:9,0:9:21:0,21,315 0/0:4,0:4:12:0,12,147 0/0:5,0:5:15:0,15,189 0/0:4,0:4:12:0,12,151 0/0:30,0:30:87:0,87,1128 0/0:33,0:33:87:0,87,1305 0/0:12,0:12:26:0,26,398 0/0:13,0:13:36:0,36,540 0/0:15,0:15:36:0,36,540 0/0:22,0:22:57:0,57,855 0/0:12,0:12:30:0,30,450 0/0:13,0:13:33:0,33,484 0/0:13,0:13:36:0,36,540 0/0:16,0:16:26:0,26,484 0/0:15,0:15:33:0,33,495 0/0:30,0:30:63:0,63,945 0/0:8,0:8:24:0,24,281 0/0:13,0:13:21:0,21,450 0/0:7,0:7:21:0,21,263 0/0:20,0:20:48:0,48,720 0/0:14,0:14:36:0,36,540 0/0:11,0:11:30:0,30,450 0/0:22,0:22:60:0,60,900 0/0:21,0:21:48:0,48,720 0/0:9,0:9:21:0,21,315 0/0:16,0:16:45:0,45,652 0/0:24,0:24:63:0,63,896 0/0:11,0:11:24:0,24,391 0/1:12,16:28:99:522,0,367 0/0:15,0:15:42:0,42,561 0/0:18,0:18:51:0,51,662 0/0:15,0:15:32:0,32,540 0/0:12,0:12:24:0,24,381 0/0:8,0:8:15:0,15,225 0/0:8,0:8:21:0,21,311 0/0:13,0:13:39:0,39,438 0/0:14,0:14:22:0,22,518 0/0:30,0:30:74:0,74,1125 0/0:17,0:17:27:0,27,630 0/0:13,0:13:20:0,20,386 0/0:16,0:16:42:0,42,630 0/0:13,0:13:36:0,36,540 0/0:16,0:16:39:0,39,585 0/0:27,0:27:62:0,62,945 0/0:25,0:25:60:0,60,900 0/0:8,0:8:24:0,24,285 0/0:8,0:8:21:0,21,300 0/0:4,0:4:12:0,12,147 0/0:6,0:6:18:0,18,206 0/0:15,0:15:36:0,36,540 0/0:5,0:5:12:0,12,154 0/0:14,0:14:42:0,42,510 0/0:11,0:11:22:0,22,360 0/0:21,0:21:60:0,60,900 0/0:4,0:4:12:0,12,141 0/0:8,0:8:21:0,21,315 0/0:7,0:7:21:0,21,249 0/0:5,0:5:15:0,15,179 0/0:11,0:11:27:0,27,395 0/0:7,0:7:21:0,21,236 0/0:14,0:14:39:0,39,585 0/0:3,0:3:9:0,9,95 0/0:5,0:5:15:0,15,187 0/0:8,0:8:21:0,21,266 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,315 0/0:16,0:16:45:0,45,675 0/0:11,0:11:33:0,33,406 0/0:3,0:3:9:0,9,135 0/0:10,0:10:27:0,27,405 0/0:26,0:26:69:0,69,1035 0/0:16,0:16:48:0,48,560 0/0:9,0:9:27:0,27,325 0/0:12,0:12:27:0,27,405 0/0:4,0:4:12:0,12,137 0/0:19,0:19:54:0,54,810 0/0:9,0:9:24:0,24,360 0/0:5,0:5:12:0,12,180 0/0:9,0:9:21:0,21,284 0/0:10,0:10:22:0,22,314 0/0:3,0:3:9:0,9,108 +20 17479423 rs185188648 T C 103.84 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.466;AN=200;InbreedingCoeff=-0.0075;AF=5.747E-4;GQ_STDDEV=16.04;FS=2.632;DP=10433;GQ_MEAN=30.92;POSITIVE_TRAIN_SITE;VQSLOD=2.75;ClippingRankSum=-0.143;BaseQRankSum=1.53;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=9.44;DB;MQRankSum=1.19;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:16,0:16:45:0,45,675 0/0:7,0:7:21:0,21,259 0/0:12,0:12:36:0,36,435 0/0:10,0:10:27:0,27,371 0/0:8,0:8:24:0,24,295 0/0:14,0:14:42:0,42,487 0/0:15,0:15:45:0,45,558 0/0:4,0:4:12:0,12,142 0/0:20,0:20:60:0,60,781 0/0:8,0:8:21:0,21,315 0/0:7,0:7:18:0,18,270 0/0:8,0:8:24:0,24,261 0/0:12,0:12:36:0,36,423 0/0:8,0:8:21:0,21,255 0/0:21,0:21:60:0,60,900 0/0:7,0:7:21:0,21,261 0/0:6,0:6:9:0,9,135 0/0:7,0:7:21:0,21,251 0/0:8,0:8:24:0,24,283 0/0:9,0:9:21:0,21,315 0/0:4,0:4:12:0,12,147 0/0:5,0:5:15:0,15,189 0/0:7,0:7:21:0,21,262 0/0:30,0:30:87:0,87,1128 0/0:33,0:33:87:0,87,1305 0/0:12,0:12:26:0,26,398 0/0:13,0:13:36:0,36,540 0/0:15,0:15:36:0,36,540 0/0:23,0:23:60:0,60,900 0/0:12,0:12:30:0,30,450 0/0:13,0:13:33:0,33,484 0/0:13,0:13:36:0,36,540 0/0:16,0:16:26:0,26,484 0/0:15,0:15:33:0,33,495 0/0:30,0:30:63:0,63,945 0/0:8,0:8:24:0,24,281 0/0:13,0:13:21:0,21,450 0/0:7,0:7:21:0,21,263 0/0:20,0:20:48:0,48,720 0/0:14,0:14:36:0,36,540 0/0:11,0:11:30:0,30,450 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/1:6,5:11:99:154,0,154 0/0:16,0:16:45:0,45,652 0/0:24,0:24:63:0,63,896 0/0:11,0:11:24:0,24,391 0/0:28,0:28:66:0,66,990 0/0:15,0:15:42:0,42,561 0/0:18,0:18:51:0,51,662 0/0:15,0:15:32:0,32,540 0/0:12,0:12:24:0,24,381 0/0:8,0:8:15:0,15,225 0/0:8,0:8:21:0,21,311 0/0:13,0:13:39:0,39,438 0/0:14,0:14:22:0,22,518 0/0:30,0:30:74:0,74,1125 0/0:17,0:17:27:0,27,630 0/0:13,0:13:20:0,20,386 0/0:16,0:16:42:0,42,630 0/0:13,0:13:36:0,36,540 0/0:16,0:16:39:0,39,585 0/0:27,0:27:62:0,62,945 0/0:25,0:25:60:0,60,900 0/0:8,0:8:24:0,24,285 0/0:8,0:8:21:0,21,300 0/0:4,0:4:12:0,12,147 0/0:6,0:6:18:0,18,206 0/0:15,0:15:36:0,36,540 0/0:5,0:5:12:0,12,154 0/0:14,0:14:42:0,42,510 0/0:11,0:11:22:0,22,360 0/0:21,0:21:28:0,28,678 0/0:4,0:4:12:0,12,141 0/0:8,0:8:21:0,21,277 0/0:6,0:6:15:0,15,213 0/0:5,0:5:15:0,15,179 0/0:11,0:11:27:0,27,395 0/0:7,0:7:21:0,21,236 0/0:14,0:14:39:0,39,585 0/0:3,0:3:9:0,9,95 0/0:7,0:7:21:0,21,238 0/0:8,0:8:21:0,21,266 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,315 0/0:16,0:16:45:0,45,675 0/0:11,0:11:33:0,33,406 0/0:3,0:3:9:0,9,135 0/0:10,0:10:27:0,27,405 0/0:26,0:26:69:0,69,1035 0/0:16,0:16:48:0,48,560 0/0:9,0:9:27:0,27,325 0/0:12,0:12:27:0,27,405 0/0:4,0:4:12:0,12,137 0/0:19,0:19:54:0,54,810 0/0:9,0:9:24:0,24,360 0/0:5,0:5:12:0,12,180 0/0:9,0:9:21:0,21,284 0/0:10,0:10:22:0,22,314 0/0:3,0:3:9:0,9,108 +20 17479616 . C T 4604.69 PASS HWP=1.0;AC=3;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=2.8;AN=200;InbreedingCoeff=-0.0017;AF=0.001724;GQ_STDDEV=89.41;FS=0.373;DP=21221;GQ_MEAN=68.88;VQSLOD=1.49;ClippingRankSum=-2.156;BaseQRankSum=-0.16;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=11.78;MQRankSum=0.108;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/1:60,52:112:99:1381,0,1568 0/0:23,0:23:60:0,60,900 0/0:22,0:22:63:0,63,780 0/0:23,0:23:60:0,60,900 0/0:32,0:32:83:0,83,1305 0/0:24,0:24:60:0,60,900 0/1:47,45:92:99:1309,0,1237 0/0:20,0:20:60:0,60,781 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,723 0/0:27,0:27:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:24,0:24:60:0,60,859 0/0:25,0:25:65:0,65,881 0/0:24,0:24:63:0,63,851 0/0:24,0:24:63:0,63,945 0/0:20,0:20:60:0,60,744 0/0:24,0:24:60:0,60,847 0/0:21,0:21:63:0,63,749 0/0:30,0:30:87:0,87,1128 0/0:33,0:33:87:0,87,1305 0/0:21,0:21:60:0,60,671 0/0:26,0:26:78:0,78,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:110,77:187:99:2016,0,3329 0/0:23,0:23:63:0,63,945 0/0:31,0:31:87:0,87,1283 0/0:21,0:21:60:0,60,900 0/0:26,0:26:75:0,75,871 0/0:30,0:30:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:29,0:29:64:0,64,919 0/0:23,0:23:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:23,0:23:60:0,60,896 0/0:23,0:23:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,793 0/0:23,0:23:63:0,63,780 0/0:24,0:24:63:0,63,896 0/0:22,0:22:63:0,63,945 0/0:29,0:29:75:0,75,1011 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:27,0:27:78:0,78,1170 0/0:25,0:25:69:0,69,1035 0/0:27,0:27:69:0,69,1035 0/0:25,0:25:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:30,0:30:75:0,75,1185 0/0:30,0:30:74:0,74,1125 0/0:25,0:25:61:0,61,922 0/0:22,0:22:66:0,66,798 0/0:22,0:22:60:0,60,853 0/0:22,0:22:60:0,60,756 0/0:22,0:22:63:0,63,945 0/0:27,0:27:62:0,62,945 0/0:22,0:22:60:0,60,821 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,862 0/0:23,0:23:60:0,60,900 0/0:30,0:30:75:0,75,1125 0/0:21,0:21:60:0,60,802 0/0:32,0:32:90:0,90,1350 0/0:20,0:20:60:0,60,699 0/0:22,0:22:63:0,63,940 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,817 0/0:20,0:20:60:0,60,803 0/0:22,0:22:60:0,60,741 0/0:22,0:22:60:0,60,900 0/0:28,0:28:66:0,66,1124 0/0:34,0:34:72:0,72,1080 0/0:22,0:22:63:0,63,772 0/0:23,0:23:60:0,60,895 0/0:24,0:24:61:0,61,945 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:26,0:26:78:0,78,1005 0/0:22,0:22:63:0,63,945 0/0:29,0:29:75:0,75,1125 0/0:22,0:22:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:21,0:21:60:0,60,711 0/0:20,0:20:60:0,60,733 0/0:29,0:29:81:0,81,1148 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:23,0:23:63:0,63,800 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,820 +20 17479617 rs11537702 G A 52925.50 PASS HWP=0.6472;AC=9;culprit=FS;MQ0=0;ReadPosRankSum=0.797;AN=200;InbreedingCoeff=0.0335;AF=0.021;GQ_STDDEV=286.86;FS=0.0;DP=24065;GQ_MEAN=116.72;POSITIVE_TRAIN_SITE;VQSLOD=6.69;ClippingRankSum=0.228;BaseQRankSum=0.893;MLEAF=0.021;MLEAC=37;MQ=59.67;QD=13.16;DB;MQRankSum=0.434;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:22,0:22:63:0,63,780 0/0:23,0:23:60:0,60,900 0/0:32,0:32:83:0,83,1305 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:20,0:20:60:0,60,781 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,723 0/0:27,0:27:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:24,0:24:60:0,60,859 0/0:25,0:25:65:0,65,881 0/0:24,0:24:63:0,63,851 0/1:91,70:161:99:1896,0,2528 0/0:20,0:20:60:0,60,744 0/0:24,0:24:60:0,60,847 0/0:21,0:21:63:0,63,749 0/0:30,0:30:87:0,87,1128 0/0:33,0:33:87:0,87,1305 0/0:21,0:21:60:0,60,671 0/0:26,0:26:78:0,78,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/1:80,67:147:99:1748,0,2152 0/0:21,0:21:60:0,60,900 0/0:26,0:26:75:0,75,871 0/0:30,0:30:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:29,0:29:64:0,64,919 0/0:23,0:23:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:23,0:23:60:0,60,896 0/0:23,0:23:60:0,60,900 0/1:33,44:77:99:1318,0,837 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,793 0/0:23,0:23:63:0,63,780 0/0:24,0:24:63:0,63,896 0/0:22,0:22:63:0,63,945 0/0:29,0:29:75:0,75,1011 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:27,0:27:78:0,78,1170 0/0:25,0:25:69:0,69,1035 0/1:44,47:91:99:1287,0,1175 0/0:25,0:25:66:0,66,990 0/0:22,0:22:60:0,60,900 0/1:51,49:100:99:1327,0,1366 0/0:30,0:30:74:0,74,1125 0/0:25,0:25:61:0,61,922 0/0:22,0:22:66:0,66,798 0/0:22,0:22:60:0,60,853 0/0:22,0:22:60:0,60,756 0/0:22,0:22:63:0,63,945 0/1:132,92:224:99:2496,0,4064 0/0:22,0:22:60:0,60,821 0/0:24,0:24:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,862 0/0:23,0:23:60:0,60,900 0/1:100,70:170:99:2034,0,2856 0/0:21,0:21:60:0,60,802 0/1:78,66:144:99:1878,0,2155 0/0:20,0:20:60:0,60,699 0/0:22,0:22:63:0,63,940 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,817 0/1:43,46:89:99:1321,0,1175 0/0:22,0:22:60:0,60,741 0/0:22,0:22:60:0,60,900 0/0:28,0:28:66:0,66,1124 0/0:34,0:34:72:0,72,1080 0/0:22,0:22:63:0,63,772 0/0:23,0:23:60:0,60,895 0/0:24,0:24:61:0,61,945 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:26,0:26:78:0,78,1005 0/0:22,0:22:63:0,63,945 0/0:29,0:29:75:0,75,1125 0/0:22,0:22:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/0:21,0:21:60:0,60,711 0/0:20,0:20:60:0,60,733 0/0:29,0:29:81:0,81,1148 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:23,0:23:63:0,63,800 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,820 +20 17479730 rs6111549 T C 405168.00 PASS HWP=0.0538;AC=57;culprit=MQ;MQ0=0;ReadPosRankSum=0.244;AN=200;InbreedingCoeff=0.0663;AF=0.329;GQ_STDDEV=298.83;FS=0.0;DP=27992;GQ_MEAN=258.64;POSITIVE_TRAIN_SITE;VQSLOD=6.88;ClippingRankSum=-0.181;BaseQRankSum=3.36;MLEAF=0.329;MLEAC=573;MQ=60.0;QD=22.22;DB;MQRankSum=0.057;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:23,0:23:60:0,60,900 0/1:17,14:31:99:451,0,537 0/0:23,0:23:60:0,60,900 0/0:32,0:32:83:0,83,1305 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:20,0:20:60:0,60,781 0/1:16,15:31:99:479,0,453 0/0:29,0:29:55:0,55,1052 0/0:27,0:27:63:0,63,945 0/1:27,24:51:99:790,0,844 0/0:22,0:22:60:0,60,900 1/1:0,31:31:93:1125,93,0 0/1:15,25:40:99:826,0,433 0/1:12,16:28:99:514,0,361 0/0:25,0:25:65:0,65,881 0/1:20,23:43:99:740,0,626 0/1:11,26:37:99:853,0,292 0/1:15,20:35:99:660,0,455 0/1:22,18:40:99:564,0,716 0/0:21,0:21:63:0,63,749 0/1:41,41:82:99:1355,0,1285 0/0:33,0:33:87:0,87,1305 0/1:19,16:35:99:527,0,575 0/1:32,25:57:99:791,0,1019 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:59,0:59:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/1:14,9:23:99:322,0,439 0/1:30,44:74:99:1498,0,835 0/1:55,41:96:99:1354,0,1649 0/0:30,0:30:63:0,63,945 0/1:7,11:18:99:404,0,206 1/1:0,19:19:57:828,57,0 0/1:30,25:55:99:767,0,940 0/1:18,24:42:99:825,0,512 0/0:23,0:23:60:0,60,896 0/0:23,0:23:60:0,60,900 0/0:32,0:32:75:0,75,1125 0/1:18,24:42:99:814,0,545 0/1:19,17:36:99:593,0,597 0/0:23,0:23:63:0,63,780 0/0:24,0:24:63:0,63,896 1/1:0,50:50:99:1965,150,0 0/0:29,0:29:75:0,75,1011 0/1:18,20:38:99:728,0,568 1/1:0,60:60:99:2476,181,0 0/1:21,28:49:99:980,0,569 0/1:15,19:34:99:647,0,473 0/1:14,20:34:99:682,0,396 0/0:25,0:25:66:0,66,990 0/1:25,43:68:99:1535,0,665 0/1:23,16:39:99:482,0,677 0/1:33,28:61:99:959,0,1006 0/0:25,0:25:61:0,61,922 0/0:22,0:22:66:0,66,798 1/1:0,58:58:99:2453,174,0 0/0:22,0:22:60:0,60,756 0/0:22,0:22:63:0,63,945 0/0:82,0:82:99:0,120,1800 0/0:22,0:22:60:0,60,821 0/0:24,0:24:63:0,63,945 1/1:0,41:41:99:1559,123,0 1/1:0,20:20:60:822,60,0 0/1:5,9:14:99:283,0,137 0/0:58,0:58:99:0,120,1800 0/0:24,0:24:60:0,60,900 0/0:42,0:42:99:0,102,1530 0/1:20,13:33:99:446,0,644 0/1:37,37:74:99:1344,0,1127 0/0:21,0:21:60:0,60,900 0/1:11,18:29:99:690,0,261 0/0:29,0:29:75:0,75,1125 0/0:30,0:30:60:0,60,1041 0/1:20,12:32:99:422,0,632 0/1:18,14:32:99:476,0,526 0/1:18,15:33:99:501,0,563 0/0:22,0:22:63:0,63,772 0/1:15,9:24:99:317,0,490 0/0:24,0:24:61:0,61,945 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/1:31,35:66:99:1283,0,929 1/1:0,28:28:84:1201,84,0 0/0:24,0:24:36:0,36,630 0/0:22,0:22:60:0,60,900 0/0:26,0:26:69:0,69,1035 0/1:22,12:34:99:414,0,697 0/0:16,0:16:39:0,39,585 0/1:21,18:39:99:597,0,655 0/1:12,16:28:99:578,0,362 0/0:21,0:21:48:0,48,720 0/1:6,13:19:99:497,0,170 0/1:6,18:24:99:656,0,155 0/0:26,0:26:60:0,60,900 0/0:16,0:16:42:0,42,609 0/0:22,0:22:60:0,60,820 +20 17489594 rs140834233 C T 1838.17 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.335;AN=200;InbreedingCoeff=-0.0137;AF=0.005178;GQ_STDDEV=27.28;FS=0.595;DP=13357;GQ_MEAN=40.65;POSITIVE_TRAIN_SITE;VQSLOD=2.85;ClippingRankSum=-0.38;BaseQRankSum=-1.415;MLEAF=0.005178;MLEAC=9;MQ=59.15;QD=11.35;DB;MQRankSum=-0.412;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,819 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:19,0:19:51:0,51,670 0/0:22,0:22:60:0,60,707 0/0:8,0:8:21:0,21,315 0/0:10,0:10:24:0,24,359 0/0:21,0:21:60:0,60,802 0/0:20,0:20:60:0,60,694 0/0:12,0:12:24:0,24,360 0/0:10,0:10:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,770 0/0:10,0:10:0:0,0,270 0/0:8,0:8:21:0,21,275 0/0:10,0:10:21:0,21,315 0/0:7,0:7:21:0,21,250 0/0:3,0:3:6:0,6,90 0/0:7,0:7:21:0,21,247 0/0:8,0:8:21:0,21,307 0/0:7,0:7:21:0,21,211 0/0:8,0:8:18:0,18,270 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:7,0:7:21:0,21,275 0/0:22,0:22:60:0,60,688 0/0:21,0:21:60:0,60,834 0/0:13,0:13:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:13,0:13:28:0,28,409 0/0:21,0:21:60:0,60,661 0/0:22,0:22:60:0,60,819 0/0:2,0:2:6:0,6,70 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,312 0/0:10,0:10:20:0,20,315 0/0:7,0:7:21:0,21,234 0/0:8,0:8:21:0,21,209 0/0:7,0:7:21:0,21,230 0/0:10,0:10:23:0,23,318 0/0:10,0:10:24:0,24,360 0/0:7,0:7:21:0,21,201 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,752 0/0:22,0:22:54:0,54,810 0/0:10,0:10:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,238 0/0:8,0:8:21:0,21,280 0/0:9,0:9:24:0,24,267 0/0:10,0:10:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,263 0/0:27,0:27:63:0,63,945 0/0:7,0:7:21:0,21,232 0/0:7,0:7:21:0,21,245 0/0:7,0:7:21:0,21,205 0/0:7,0:7:21:0,21,195 0/0:8,0:8:21:0,21,315 0/0:22,0:22:60:0,60,632 0/0:3,0:3:9:0,9,91 0/0:7,0:7:21:0,21,255 0/0:8,0:8:21:0,21,245 0/0:9,0:9:24:0,24,309 0/0:5,0:5:6:0,6,90 0/0:4,0:4:6:0,6,118 0/0:7,0:7:21:0,21,234 0/0:7,0:7:21:0,21,239 0/0:7,0:7:21:0,21,243 0/0:8,0:8:21:0,21,288 0/0:10,0:10:21:0,21,315 0/0:4,0:4:9:0,9,112 0/0:8,0:8:21:0,21,253 0/0:11,0:11:18:0,18,270 0/0:7,0:7:21:0,21,280 0/1:2,5:7:56:124,0,56 0/0:8,0:8:21:0,21,311 0/0:25,0:25:60:0,60,802 0/0:25,0:25:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:27,0:27:62:0,62,868 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,666 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,238 0/0:22,0:22:60:0,60,900 0/0:12,0:12:24:0,24,360 0/0:2,0:2:6:0,6,68 0/0:7,0:7:20:0,20,247 0/0:7,0:7:21:0,21,207 0/0:7,0:7:21:0,21,261 +20 17492755 rs1559956 C T 289384.00 PASS HWP=0.0072;AC=55;culprit=MQ;MQ0=0;ReadPosRankSum=0.199;AN=200;InbreedingCoeff=0.0886;AF=0.373;GQ_STDDEV=180.31;FS=0.0;DP=21574;GQ_MEAN=166.79;POSITIVE_TRAIN_SITE;VQSLOD=6.75;ClippingRankSum=-0.197;BaseQRankSum=2.86;MLEAF=0.374;MLEAC=651;MQ=60.0;QD=21.61;DB;MQRankSum=0.112;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:13,12:25:99:376,0,389 0/0:21,0:21:23:0,23,671 0/1:11,12:23:99:390,0,297 0/0:17,0:17:39:0,39,585 0/0:25,0:25:35:0,35,803 0/0:17,0:17:26:0,26,675 0/1:17,10:27:99:308,0,514 0/0:21,0:21:60:0,60,743 0/1:11,13:24:99:433,0,327 0/0:15,0:15:39:0,39,585 0/0:25,0:25:63:0,63,945 0/0:10,0:10:24:0,24,360 1/1:0,30:30:90:1160,90,0 0/1:6,11:17:99:375,0,144 1/1:0,24:24:72:852,72,0 1/1:0,21:21:63:799,63,0 1/1:0,22:22:66:841,66,0 0/1:10,9:19:99:290,0,281 0/1:6,7:13:99:227,0,173 1/1:0,32:32:96:1202,96,0 0/1:12,10:22:99:299,0,362 0/0:20,0:20:39:0,39,585 0/0:22,0:22:60:0,60,900 0/1:18,12:30:99:391,0,595 0/0:32,0:32:66:0,66,990 0/1:13,11:24:99:345,0,350 0/1:19,11:30:99:331,0,525 0/0:19,0:19:39:0,39,585 0/0:27,0:27:63:0,63,945 0/0:21,0:21:51:0,51,765 0/1:11,14:25:99:415,0,264 1/1:0,29:29:87:1118,87,0 0/0:39,0:39:93:0,93,1395 0/0:40,0:40:99:0,102,1530 0/0:35,0:35:69:0,69,1035 1/1:0,19:19:57:699,57,0 1/1:1,18:19:18:668,18,0 0/1:13,11:24:99:357,0,390 0/0:33,0:33:69:0,69,1035 0/0:28,0:28:69:0,69,1035 0/1:5,14:19:99:485,0,106 0/1:10,11:21:99:351,0,262 0/0:27,0:27:65:0,65,976 0/0:27,0:27:60:0,60,900 0/1:11,15:26:99:477,0,293 0/1:17,4:21:86:86,0,516 0/1:22,22:44:99:699,0,562 0/0:26,0:26:66:0,66,990 0/0:29,0:29:63:0,63,945 0/0:33,0:33:87:0,87,1305 0/1:17,15:32:99:460,0,434 0/0:27,0:27:66:0,66,990 0/0:24,0:24:66:0,66,990 0/0:10,0:10:24:0,24,360 0/1:18,7:25:99:192,0,565 0/0:28,0:28:78:0,78,1170 0/0:28,0:28:75:0,75,1125 0/0:27,0:27:75:0,75,1125 0/1:10,18:28:99:541,0,258 0/1:33,28:61:99:907,0,972 0/1:9,12:21:99:398,0,239 0/0:25,0:25:69:0,69,1035 0/0:53,0:53:99:0,114,1710 0/1:11,20:31:99:625,0,288 0/1:13,9:22:99:245,0,373 0/0:21,0:21:42:0,42,630 0/0:7,0:7:21:0,21,278 0/1:4,10:14:99:348,0,108 0/0:34,0:34:77:0,77,1170 0/0:13,0:13:24:0,24,405 0/1:13,19:32:99:597,0,389 0/0:16,0:16:33:0,33,495 0/0:27,0:27:60:0,60,900 0/0:16,0:16:45:0,45,618 0/0:22,0:22:60:0,60,900 0/0:14,0:14:24:0,24,495 0/1:7,16:23:99:518,0,192 0/0:14,0:14:30:0,30,450 0/1:9,8:17:99:257,0,278 0/0:23,0:23:60:0,60,900 0/0:9,0:9:24:0,24,360 0/1:11,10:21:99:333,0,312 0/1:3,9:12:76:314,0,76 0/0:20,0:20:48:0,48,720 0/1:10,6:16:99:183,0,313 0/0:30,0:30:60:0,60,900 0/0:20,0:20:39:0,39,585 0/0:17,0:17:39:0,39,585 0/0:28,0:28:75:0,75,1125 0/0:29,0:29:78:0,78,1170 1/1:0,32:32:96:1212,96,0 0/0:15,0:15:30:0,30,450 0/1:13,10:23:99:319,0,406 1/1:0,17:17:51:647,51,0 0/0:18,0:18:45:0,45,675 0/1:11,10:21:99:334,0,324 0/1:6,7:13:99:232,0,168 0/0:22,0:22:60:0,60,900 0/0:13,0:13:33:0,33,495 0/0:19,0:19:48:0,48,720 +20 17495328 rs6080731 G A 9313.33 PASS HWP=1.0;AC=4;culprit=MQRankSum;MQ0=0;ReadPosRankSum=0.863;AN=200;InbreedingCoeff=-0.0035;AF=0.003448;GQ_STDDEV=121.77;FS=1.742;DP=41248;GQ_MEAN=100.4;POSITIVE_TRAIN_SITE;VQSLOD=4.17;ClippingRankSum=-0.85;BaseQRankSum=-4.076;MLEAF=0.003448;MLEAC=6;MQ=59.78;QD=14.69;DB;MQRankSum=-0.651;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:49,0:49:99:0,120,1800 0/0:35,0:35:82:0,82,1260 0/0:45,0:45:96:0,96,1440 0/0:53,0:53:99:0,120,1800 0/0:41,0:41:87:0,87,1305 0/0:61,0:61:99:0,120,1800 0/0:49,0:49:99:0,108,1620 0/0:43,0:43:99:0,99,1485 0/0:48,0:48:99:0,111,1665 0/0:29,0:29:75:0,75,1125 0/0:52,0:52:99:0,117,1755 0/0:41,0:41:90:0,90,1350 0/0:42,0:42:84:0,84,1260 0/0:47,0:47:99:0,108,1620 0/0:25,0:25:60:0,60,900 0/0:35,0:35:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:35,0:35:81:0,81,1215 0/0:31,0:31:67:0,67,1080 0/0:34,0:34:78:0,78,1170 0/0:29,0:29:63:0,63,945 0/0:32,0:32:72:0,72,1080 0/0:39,0:39:84:0,84,1260 0/0:98,0:98:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:35,0:35:72:0,72,1080 0/0:65,0:65:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:32,0:32:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:62,0:62:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:36,0:36:88:0,88,1440 0/0:48,0:48:99:0,117,1755 0/1:55,63:118:99:1907,0,1716 0/0:65,0:65:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/1:55,48:103:99:1432,0,1796 0/0:63,0:63:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:55,0:55:99:0,117,1755 0/0:31,0:31:72:0,72,1080 0/0:33,0:33:66:0,66,990 0/0:65,0:65:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:50,0:50:99:0,102,1530 0/0:49,0:49:99:0,108,1620 0/0:54,0:54:99:0,120,1800 0/0:110,0:110:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:34,0:34:66:0,66,990 0/0:29,0:29:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:62,0:62:99:0,120,1800 0/0:34,0:34:99:0,99,1214 0/0:55,0:55:99:0,117,1755 0/1:67,61:128:99:1858,0,2263 0/0:52,0:52:99:0,117,1755 0/0:43,0:43:84:0,84,1260 0/1:46,55:101:99:1759,0,1460 0/0:26,0:26:60:0,60,900 0/0:33,0:33:84:0,84,1260 0/0:41,0:41:87:0,87,1305 0/0:34,0:34:63:0,63,945 0/0:44,0:44:99:0,111,1665 0/0:29,0:29:75:0,75,1125 0/0:35,0:35:81:0,81,1305 0/0:28,0:28:66:0,66,990 0/0:42,0:42:87:0,87,1305 0/0:30,0:30:66:0,66,1035 0/0:48,0:48:99:0,117,1755 0/0:26,0:26:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:30,0:30:69:0,69,1035 0/0:71,0:71:99:0,120,1800 0/0:31,0:31:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:42,0:42:86:0,86,1440 0/0:36,0:36:69:0,69,1035 0/0:33,0:33:84:0,84,1260 0/0:38,0:38:75:0,75,1125 0/0:26,0:26:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:42,0:42:87:0,87,1305 +20 17581613 rs149130905 A G 2976.31 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.599;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=77.2;FS=4.072;DP=20942;GQ_MEAN=68.15;VQSLOD=0.991;ClippingRankSum=0.65;BaseQRankSum=5.98;MLEAF=0.001149;MLEAC=2;MQ=57.55;QD=14.73;DB;MQRankSum=-0.105;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:66:0,66,990 0/0:22,0:22:63:0,63,880 0/0:22,0:22:62:0,62,843 0/0:21,0:21:60:0,60,784 0/0:24,0:24:60:0,60,900 0/0:21,0:21:63:0,63,736 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,898 0/0:21,0:21:63:0,63,801 0/0:21,0:21:60:0,60,900 0/0:24,0:24:69:0,69,834 0/0:22,0:22:60:0,60,768 0/0:20,0:20:60:0,60,741 0/0:30,0:30:81:0,81,1196 0/0:28,0:28:76:0,76,1041 0/0:20,0:20:60:0,60,705 0/0:31,0:31:87:0,87,1305 0/0:22,0:22:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,700 0/0:21,0:21:63:0,63,724 0/0:25,0:25:69:0,69,966 0/0:20,0:20:60:0,60,691 0/0:20,0:20:60:0,60,685 0/0:21,0:21:60:0,60,798 0/0:23,0:23:63:0,63,829 0/0:20,0:20:60:0,60,685 0/0:25,0:25:69:0,69,1004 0/0:23,0:23:60:0,60,859 0/0:23,0:23:63:0,63,837 0/0:24,0:24:63:0,63,918 0/0:27,0:27:75:0,75,1125 0/0:38,0:38:99:0,105,1575 0/0:31,0:31:78:0,78,1170 0/0:20,0:20:60:0,60,696 0/0:21,0:21:60:0,60,803 0/0:21,0:21:60:0,60,770 0/0:22,0:22:63:0,63,945 0/0:31,0:31:87:0,87,1305 0/0:28,0:28:78:0,78,1170 0/0:20,0:20:60:0,60,768 0/0:20,0:20:60:0,60,738 0/0:25,0:25:72:0,72,1035 0/0:20,0:20:60:0,60,715 0/0:23,0:23:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:33,0:33:71:0,71,1234 0/0:21,0:21:60:0,60,900 0/0:27,0:27:81:0,81,986 0/0:22,0:22:60:0,60,900 0/0:42,0:42:99:0,103,1317 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,763 0/0:21,0:21:60:0,60,753 0/0:27,0:27:70:0,70,960 0/0:42,0:42:99:0,117,1755 0/0:35,0:35:93:0,93,1395 0/0:27,0:27:81:0,81,1015 0/0:30,0:30:87:0,87,1305 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:24,0:24:66:0,66,988 0/0:27,0:27:69:0,69,1080 0/0:21,0:21:63:0,63,732 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:38,30:68:99:858,0,1243 0/0:21,0:21:60:0,60,900 0/0:23,0:23:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:66:0,66,848 0/0:20,0:20:60:0,60,655 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,945 0/1:69,65:134:99:2195,0,2180 0/0:20,0:20:60:0,60,729 0/0:20,0:20:60:0,60,698 0/0:22,0:22:63:0,63,945 0/0:22,0:22:63:0,63,945 0/0:28,0:28:70:0,70,904 0/0:23,0:23:66:0,66,940 0/0:22,0:22:60:0,60,900 0/0:22,0:22:61:0,61,743 0/0:25,0:25:75:0,75,924 0/0:21,0:21:60:0,60,818 0/0:21,0:21:60:0,60,900 0/0:34,0:34:81:0,81,1215 0/0:29,0:29:81:0,81,1215 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:28,0:28:74:0,74,1155 0/0:22,0:22:60:0,60,850 0/0:21,0:21:60:0,60,900 +20 17587669 rs144850804 T G 9020.22 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=-0.497;AN=200;InbreedingCoeff=-0.0052;AF=0.005172;GQ_STDDEV=86.73;FS=0.843;DP=25493;GQ_MEAN=78.71;POSITIVE_TRAIN_SITE;VQSLOD=3.54;ClippingRankSum=0.659;BaseQRankSum=4.72;MLEAF=0.005172;MLEAC=9;MQ=60.0;QD=15.94;DB;MQRankSum=0.496;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:32,0:32:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:31,0:31:66:0,66,990 0/0:25,0:25:66:0,66,990 0/0:20,0:20:60:0,60,674 0/0:24,0:24:69:0,69,1035 0/0:27,0:27:69:0,69,1080 0/0:23,0:23:66:0,66,791 0/0:30,0:30:60:0,60,900 0/0:21,0:21:63:0,63,772 0/0:30,0:30:75:0,75,1125 0/0:21,0:21:60:0,60,900 0/0:26,0:26:72:0,72,1080 0/0:21,0:21:60:0,60,785 0/0:36,0:36:87:0,87,1305 0/0:31,0:31:63:0,63,945 0/0:39,0:39:81:0,81,1215 0/0:39,0:39:87:0,87,1304 0/0:31,0:31:75:0,75,1125 0/1:50,68:118:99:2071,0,1426 0/0:38,0:38:95:0,95,1383 0/0:48,0:48:99:0,109,1624 0/0:38,0:38:76:0,76,1374 0/0:22,0:22:60:0,60,885 0/0:31,0:31:63:0,63,945 0/0:34,0:34:81:0,81,1240 0/0:36,0:36:90:0,90,1350 0/0:34,0:34:87:0,87,1305 0/0:27,0:27:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:30,23:53:99:745,0,960 0/0:57,0:57:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:21,0:21:60:0,60,822 0/0:20,0:20:60:0,60,798 0/0:28,0:28:78:0,78,1170 0/0:31,0:31:75:0,75,1125 0/0:32,0:32:93:0,93,1306 0/0:25,0:25:66:0,66,887 0/0:24,0:24:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:28,0:28:68:0,68,1035 0/0:28,0:28:81:0,81,988 0/0:43,0:43:99:0,105,1575 0/0:35,0:35:90:0,90,1350 0/0:39,0:39:99:0,102,1299 0/0:44,0:44:99:0,99,1485 0/0:49,0:49:90:0,90,1350 0/0:25,0:25:63:0,63,945 0/0:34,0:34:93:0,93,1395 0/0:23,0:23:60:0,60,900 0/0:29,0:29:72:0,72,1042 0/0:36,0:36:90:0,90,1240 0/0:32,0:32:67:0,67,1035 0/0:34,0:34:84:0,84,1260 0/0:47,0:47:99:0,102,1530 0/0:42,0:42:99:0,114,1710 0/0:53,0:53:99:0,120,1800 0/0:30,0:30:69:0,69,1080 0/0:39,0:39:99:0,102,1530 0/0:62,0:62:99:0,120,1800 0/0:27,0:27:68:0,68,1035 0/0:38,0:38:82:0,82,1395 0/0:40,0:40:81:0,81,1215 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,846 0/0:61,0:61:99:0,120,1800 0/0:23,0:23:60:0,60,900 0/0:48,0:48:99:0,111,1665 0/0:24,0:24:60:0,60,900 0/0:42,0:42:90:0,90,1350 0/0:27,0:27:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:34,0:34:84:0,84,1260 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:24,0:24:60:0,60,842 0/0:27,0:27:69:0,69,1024 0/0:25,0:25:72:0,72,1080 0/0:30,0:30:69:0,69,1039 0/0:26,0:26:66:0,66,990 0/0:44,0:44:96:0,96,1440 0/0:23,0:23:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:37,0:37:87:0,87,1305 0/0:44,0:44:96:0,96,1440 0/0:24,0:24:66:0,66,916 0/0:23,0:23:63:0,63,945 0/0:32,0:32:75:0,75,1115 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,782 0/0:22,0:22:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,860 0/0:22,0:22:60:0,60,900 +20 17594801 rs8803 G A 55723.30 PASS HWP=1.0;AC=9;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.718;AN=200;InbreedingCoeff=0.0036;AF=0.032;GQ_STDDEV=235.5;FS=0.0;DP=34528;GQ_MEAN=134.05;POSITIVE_TRAIN_SITE;VQSLOD=5.6;ClippingRankSum=-0.303;BaseQRankSum=-2.52;MLEAF=0.032;MLEAC=56;MQ=59.44;QD=12.27;DB;MQRankSum=0.394;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:62:0,62,1080 0/0:44,0:44:96:0,96,1440 0/0:31,0:31:75:0,75,1125 0/0:44,0:44:99:0,108,1620 0/1:40,31:71:99:834,0,1295 0/0:49,0:49:99:0,105,1575 0/0:44,0:44:99:0,108,1620 0/0:28,0:28:63:0,63,945 0/0:47,0:47:99:0,120,1800 0/0:47,0:47:99:0,111,1665 0/1:46,29:75:99:870,0,1395 0/0:31,0:31:81:0,81,1215 0/0:62,0:62:99:0,120,1800 0/0:39,0:39:93:0,93,1395 0/0:26,0:26:72:0,72,1080 0/0:49,0:49:99:0,117,1736 0/0:31,0:31:81:0,81,1215 0/0:33,0:33:84:0,84,1260 0/0:35,0:35:84:0,84,1260 0/0:36,0:36:84:0,84,1260 0/0:34,0:34:90:0,90,1350 0/0:24,0:24:60:0,60,900 0/1:30,33:63:99:974,0,854 0/0:59,0:59:99:0,111,1665 0/0:45,0:45:87:0,87,1305 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:63:0,63,945 0/1:56,51:107:99:1359,0,1867 0/0:50,0:50:99:0,113,1800 0/0:61,0:61:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:44,0:44:60:0,60,900 0/0:43,0:43:66:0,66,990 0/1:75,68:143:99:2068,0,2442 0/0:29,0:29:66:0,66,990 0/0:35,0:35:81:0,81,1215 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:37,0:37:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:66:0,66,951 0/0:40,0:40:93:0,93,1395 0/0:39,0:39:87:0,87,1305 0/0:36,0:36:73:0,73,1055 0/0:33,0:33:62:0,62,1080 0/0:35,0:35:60:0,60,900 0/0:32,0:32:72:0,72,1080 0/0:36,0:36:84:0,84,931 0/0:28,0:28:66:0,66,863 0/0:31,0:31:69:0,69,846 0/0:32,0:32:67:0,67,886 0/0:34,0:34:63:0,63,945 0/0:32,0:32:71:0,71,799 0/0:30,0:30:60:0,60,900 0/1:28,38:66:99:1099,0,789 0/0:44,0:44:69:0,69,1035 0/0:28,0:28:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:39,0:39:78:0,78,1170 0/1:18,30:48:99:921,0,656 0/0:28,0:28:60:0,60,900 0/0:41,0:41:90:0,90,1350 0/0:30,0:30:60:0,60,900 0/0:34,0:34:66:0,66,938 0/0:30,0:30:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:29,0:29:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:32,0:32:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:30,0:30:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:39,0:39:90:0,90,1350 0/0:27,0:27:60:0,60,900 0/0:39,0:39:99:0,99,1485 0/0:45,0:45:99:0,99,1485 0/0:37,0:37:78:0,78,1170 0/0:27,0:27:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:51,0:51:99:0,102,1530 0/0:37,0:37:81:0,81,1215 0/0:31,0:31:66:0,66,990 0/0:26,0:26:63:0,63,945 0/1:22,24:46:99:710,0,732 0/1:48,33:81:99:946,0,1657 +20 17594886 rs116933131 C T 12483.50 PASS HWP=0.2091;AC=6;culprit=MQ;MQ0=0;ReadPosRankSum=0.417;AN=200;InbreedingCoeff=0.0871;AF=0.011;GQ_STDDEV=75.8;FS=1.757;DP=30025;GQ_MEAN=82.48;POSITIVE_TRAIN_SITE;VQSLOD=5.2;ClippingRankSum=-0.07;BaseQRankSum=2.66;MLEAF=0.011;MLEAC=20;MQ=59.63;QD=13.48;DB;MQRankSum=0.042;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:31,0:31:62:0,62,1080 0/0:44,0:44:96:0,96,1440 0/0:31,0:31:75:0,75,1125 0/0:44,0:44:99:0,108,1620 0/0:29,0:29:72:0,72,1080 0/0:49,0:49:99:0,105,1575 0/0:44,0:44:99:0,108,1620 0/0:28,0:28:63:0,63,945 0/0:47,0:47:99:0,120,1800 0/0:47,0:47:99:0,111,1665 0/0:42,0:42:90:0,90,1350 0/0:31,0:31:81:0,81,1215 0/1:28,32:60:99:904,0,781 0/0:39,0:39:93:0,93,1395 0/0:26,0:26:72:0,72,1080 0/1:26,24:50:99:684,0,639 0/0:31,0:31:81:0,81,1215 0/0:33,0:33:84:0,84,1260 0/0:35,0:35:84:0,84,1260 0/0:36,0:36:84:0,84,1260 0/0:34,0:34:90:0,90,1350 0/0:24,0:24:60:0,60,900 0/0:33,0:33:61:0,61,1080 0/0:59,0:59:99:0,111,1665 0/0:45,0:45:87:0,87,1305 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:36,0:36:76:0,76,1072 0/0:50,0:50:99:0,113,1800 0/0:61,0:61:99:0,120,1800 0/0:33,0:33:75:0,75,1125 0/0:44,0:44:60:0,60,900 0/0:43,0:43:66:0,66,990 0/0:39,0:39:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:35,0:35:81:0,81,1215 0/0:29,0:29:60:0,60,900 0/0:17,0:17:32:0,32,501 0/0:28,0:28:63:0,63,945 0/0:18,0:18:37:0,37,481 0/0:19,0:19:24:0,24,544 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:37,0:37:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:30,0:30:66:0,66,951 0/0:40,0:40:93:0,93,1395 0/0:39,0:39:87:0,87,1305 0/0:36,0:36:73:0,73,1055 0/0:33,0:33:62:0,62,1080 0/0:13,0:13:20:0,20,356 0/0:32,0:32:72:0,72,1080 0/0:36,0:36:84:0,84,931 0/0:28,0:28:66:0,66,863 0/0:31,0:31:69:0,69,846 0/0:32,0:32:67:0,67,886 0/0:34,0:34:63:0,63,945 0/0:32,0:32:71:0,71,799 0/0:30,0:30:60:0,60,900 0/0:34,0:34:60:0,60,900 0/0:44,0:44:69:0,69,1035 0/0:28,0:28:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:39,0:39:78:0,78,1170 0/0:19,0:19:51:0,51,765 0/0:9,0:9:27:0,27,250 0/0:41,0:41:90:0,90,1350 0/0:19,0:19:36:0,36,540 0/0:34,0:34:66:0,66,938 0/0:30,0:30:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:29,0:29:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:18,0:18:36:0,36,540 0/0:32,0:32:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:21,0:21:42:0,42,764 0/0:34,0:34:60:0,60,900 0/0:20,0:20:51:0,51,629 0/0:16,0:16:27:0,27,366 0/0:30,0:30:60:0,60,900 0/0:29,0:29:54:0,54,810 0/0:23,0:23:45:0,45,675 0/0:31,0:31:60:0,60,900 0/1:26,12:38:99:324,0,653 0/0:27,0:27:60:0,60,900 0/0:39,0:39:99:0,99,1485 0/0:45,0:45:99:0,99,1485 0/0:37,0:37:78:0,78,1170 0/0:27,0:27:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:16,0:16:23:0,23,450 1/1:0,49:49:99:1586,147,0 0/1:19,18:37:99:498,0,496 0/0:15,0:15:27:0,27,405 0/0:16,0:16:39:0,39,585 0/0:18,0:18:39:0,39,585 0/0:25,0:25:60:0,60,900 +20 17595423 rs147892061 T C 696.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.475;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=29.08;FS=0.0;DP=26702;GQ_MEAN=78.77;VQSLOD=5.02;ClippingRankSum=-0.117;BaseQRankSum=1.47;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=12.01;DB;MQRankSum=0.195;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:90:0,90,1106 0/0:24,0:24:63:0,63,945 0/0:30,0:30:65:0,65,1013 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:28,0:28:70:0,70,1022 0/0:33,0:33:99:0,99,1251 0/0:20,0:20:60:0,60,773 0/0:34,0:34:87:0,87,1305 0/0:23,0:23:60:0,60,900 0/0:28,0:28:84:0,84,1072 0/0:33,0:33:99:0,99,1191 0/0:33,0:33:99:0,99,1189 0/0:30,0:30:72:0,72,1215 0/0:21,0:21:60:0,60,760 0/0:25,0:25:63:0,63,945 0/0:26,0:26:69:0,69,1035 0/0:22,0:22:63:0,63,802 0/0:22,0:22:63:0,63,933 0/0:25,0:25:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,847 0/0:24,0:24:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:33,0:33:93:0,93,1395 0/0:25,0:25:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:34,0:34:93:0,93,1395 0/0:41,0:41:81:0,81,1652 0/0:33,0:33:81:0,81,1395 0/0:43,0:43:99:0,120,1800 0/0:34,0:34:72:0,72,1080 0/0:40,0:40:99:0,99,1485 0/0:52,0:52:99:0,102,1530 0/0:21,0:21:63:0,63,707 0/0:39,0:39:99:0,111,1356 0/0:29,0:29:78:0,78,957 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:24,0:24:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:28,0:28:72:0,72,1019 0/0:35,0:35:64:0,64,1305 0/0:27,0:27:69:0,69,1027 0/0:31,0:31:75:0,75,1125 0/0:33,0:33:75:0,75,1125 0/0:25,0:25:63:0,63,945 0/0:32,0:32:84:0,84,1237 0/0:38,0:38:90:0,90,1350 0/0:29,0:29:66:0,66,985 0/0:34,0:34:61:0,61,972 0/0:29,0:29:84:0,84,984 0/0:26,0:26:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:40,0:40:99:0,105,1575 0/0:29,0:29:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:44,0:44:99:0,120,1800 0/0:31,0:31:93:0,93,1149 0/0:23,0:23:60:0,60,900 0/0:44,0:44:99:0,105,1575 0/0:28,0:28:66:0,66,990 0/0:30,0:30:78:0,78,1132 0/0:21,0:21:60:0,60,724 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,768 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:63:0,63,695 0/0:23,0:23:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:32,0:32:82:0,82,1031 0/0:26,0:26:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,859 0/0:21,0:21:60:0,60,783 0/0:27,0:27:81:0,81,946 0/0:22,0:22:60:0,60,900 0/0:29,0:29:84:0,84,1260 0/0:24,0:24:72:0,72,819 0/0:21,0:21:60:0,60,822 0/1:30,28:58:99:747,0,786 0/0:23,0:23:63:0,63,938 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,707 0/0:35,0:35:93:0,93,1395 0/0:26,0:26:78:0,78,974 0/0:23,0:23:63:0,63,945 0/0:51,0:51:99:0,120,1800 0/0:36,0:36:90:0,90,1350 0/0:33,0:33:73:0,73,1234 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:26,0:26:64:0,64,1125 0/0:26,0:26:72:0,72,1080 0/0:26,0:26:72:0,72,1080 0/0:22,0:22:60:0,60,684 0/0:30,0:30:87:0,87,946 +20 17595466 rs139306091 C A 7848.40 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.979;AN=200;InbreedingCoeff=-0.004;AF=0.004023;GQ_STDDEV=97.74;FS=0.0;DP=27190;GQ_MEAN=86.34;POSITIVE_TRAIN_SITE;VQSLOD=5.37;ClippingRankSum=0.338;BaseQRankSum=-3.907;MLEAF=0.004023;MLEAC=7;MQ=59.53;QD=11.78;DB;MQRankSum=0.491;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:90:0,90,1106 0/0:24,0:24:63:0,63,945 0/0:30,0:30:65:0,65,1013 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:28,0:28:70:0,70,1022 0/0:33,0:33:99:0,99,1251 0/0:20,0:20:60:0,60,773 0/0:34,0:34:87:0,87,1305 0/0:23,0:23:60:0,60,900 0/0:28,0:28:84:0,84,1072 0/0:33,0:33:99:0,99,1191 0/0:33,0:33:99:0,99,1189 0/0:30,0:30:72:0,72,1215 0/0:21,0:21:60:0,60,760 0/0:25,0:25:63:0,63,945 0/0:26,0:26:69:0,69,1035 0/0:22,0:22:63:0,63,802 0/0:22,0:22:63:0,63,933 0/1:39,39:78:99:1116,0,1202 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,847 0/0:24,0:24:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:33,0:33:93:0,93,1395 0/0:25,0:25:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:34,0:34:93:0,93,1395 0/0:41,0:41:81:0,81,1652 0/0:33,0:33:81:0,81,1395 0/1:58,70:128:99:2029,0,1730 0/0:34,0:34:72:0,72,1080 0/0:40,0:40:99:0,99,1485 0/0:52,0:52:99:0,102,1530 0/0:21,0:21:63:0,63,707 0/0:39,0:39:99:0,111,1356 0/0:29,0:29:78:0,78,957 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:24,0:24:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:28,0:28:72:0,72,1019 0/0:35,0:35:64:0,64,1305 0/0:27,0:27:69:0,69,1027 0/0:31,0:31:75:0,75,1125 0/0:33,0:33:75:0,75,1125 0/0:25,0:25:63:0,63,945 0/0:32,0:32:84:0,84,1237 0/0:38,0:38:90:0,90,1350 0/0:29,0:29:66:0,66,985 0/0:34,0:34:61:0,61,972 0/0:29,0:29:84:0,84,984 0/0:26,0:26:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:40,0:40:99:0,105,1575 0/0:29,0:29:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:44,0:44:99:0,120,1800 0/0:31,0:31:93:0,93,1149 0/0:23,0:23:60:0,60,900 0/0:44,0:44:99:0,105,1575 0/0:28,0:28:66:0,66,990 0/0:30,0:30:78:0,78,1132 0/0:21,0:21:60:0,60,724 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,768 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:63:0,63,695 0/0:23,0:23:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:32,0:32:82:0,82,1031 0/0:26,0:26:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,859 0/0:21,0:21:60:0,60,783 0/0:27,0:27:81:0,81,946 0/0:22,0:22:60:0,60,900 0/0:29,0:29:84:0,84,1260 0/0:24,0:24:72:0,72,819 0/0:21,0:21:60:0,60,822 0/0:31,0:31:81:0,81,1215 0/0:23,0:23:63:0,63,938 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,707 0/0:35,0:35:93:0,93,1395 0/0:26,0:26:78:0,78,974 0/0:23,0:23:63:0,63,945 0/0:51,0:51:99:0,120,1800 0/0:36,0:36:90:0,90,1350 0/0:33,0:33:73:0,73,1234 0/0:25,0:25:60:0,60,900 0/0:27,0:27:72:0,72,999 0/0:37,0:37:96:0,96,1440 0/0:26,0:26:64:0,64,1125 0/0:26,0:26:72:0,72,1080 0/0:26,0:26:72:0,72,1080 0/0:22,0:22:60:0,60,684 0/0:30,0:30:87:0,87,946 +20 17595480 . C T 1260.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.073;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=45.87;FS=0.656;DP=27596;GQ_MEAN=80.32;VQSLOD=1.73;ClippingRankSum=-0.04;BaseQRankSum=-0.257;MLEAF=5.747E-4;MLEAC=1;MQ=59.35;QD=8.82;MQRankSum=0.479;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:90:0,90,1106 0/0:24,0:24:63:0,63,945 0/0:30,0:30:65:0,65,1013 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:28,0:28:70:0,70,1022 0/0:33,0:33:99:0,99,1251 0/0:20,0:20:60:0,60,773 0/0:34,0:34:87:0,87,1305 0/0:23,0:23:60:0,60,900 0/0:28,0:28:84:0,84,1072 0/0:33,0:33:99:0,99,1191 0/0:33,0:33:99:0,99,1189 0/0:30,0:30:72:0,72,1215 0/0:21,0:21:60:0,60,760 0/0:25,0:25:63:0,63,945 0/0:26,0:26:69:0,69,1035 0/0:22,0:22:63:0,63,802 0/0:22,0:22:63:0,63,933 0/0:54,0:54:99:0,114,1710 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,847 0/0:24,0:24:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:33,0:33:93:0,93,1395 0/0:25,0:25:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:34,0:34:93:0,93,1395 0/0:41,0:41:81:0,81,1652 0/0:33,0:33:81:0,81,1395 0/0:59,0:59:99:0,120,1800 0/0:34,0:34:72:0,72,1080 0/0:40,0:40:99:0,99,1485 0/0:52,0:52:99:0,102,1530 0/0:21,0:21:63:0,63,707 0/0:39,0:39:99:0,111,1356 0/0:29,0:29:78:0,78,957 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:24,0:24:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:28,0:28:72:0,72,1019 0/0:35,0:35:64:0,64,1305 0/0:27,0:27:69:0,69,1027 0/0:31,0:31:75:0,75,1125 0/0:33,0:33:75:0,75,1125 0/0:25,0:25:63:0,63,945 0/0:32,0:32:84:0,84,1237 0/0:38,0:38:90:0,90,1350 0/0:29,0:29:66:0,66,985 0/0:34,0:34:61:0,61,972 0/0:29,0:29:84:0,84,984 0/0:26,0:26:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:40,0:40:99:0,105,1575 0/0:29,0:29:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:44,0:44:99:0,120,1800 0/0:31,0:31:93:0,93,1149 0/0:23,0:23:60:0,60,900 0/0:44,0:44:99:0,105,1575 0/0:28,0:28:66:0,66,990 0/0:30,0:30:78:0,78,1132 0/0:21,0:21:60:0,60,724 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,768 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:63:0,63,695 0/0:23,0:23:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:32,0:32:82:0,82,1031 0/0:26,0:26:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,859 0/0:21,0:21:60:0,60,783 0/0:27,0:27:81:0,81,946 0/0:22,0:22:60:0,60,900 0/0:29,0:29:84:0,84,1260 0/0:24,0:24:72:0,72,819 0/0:21,0:21:60:0,60,822 0/0:31,0:31:81:0,81,1215 0/0:23,0:23:63:0,63,938 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,707 0/0:35,0:35:93:0,93,1395 0/0:26,0:26:78:0,78,974 0/0:23,0:23:63:0,63,945 0/0:51,0:51:99:0,120,1800 0/1:90,53:143:99:1311,0,2359 0/0:33,0:33:73:0,73,1234 0/0:25,0:25:60:0,60,900 0/0:27,0:27:72:0,72,999 0/0:37,0:37:96:0,96,1440 0/0:26,0:26:64:0,64,1125 0/0:26,0:26:72:0,72,1080 0/0:26,0:26:72:0,72,1080 0/0:22,0:22:60:0,60,684 0/0:30,0:30:87:0,87,946 +20 17595540 . GT G 91852.30 PASS HWP=0.0287;AC=2;culprit=MQRankSum;MQ0=0;ReadPosRankSum=0.055;AN=200;InbreedingCoeff=0.0992;AF=0.042;GQ_STDDEV=312.3;FS=2.7;DP=31840;GQ_MEAN=161.88;POSITIVE_TRAIN_SITE;VQSLOD=3.87;ClippingRankSum=-0.33;BaseQRankSum=0.261;MLEAF=0.042;MLEAC=73;MQ=60.0;QD=14.57;MQRankSum=0.638;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:30,0:30:90:0,90,1106 0/0:24,0:24:63:0,63,945 0/0:30,0:30:65:0,65,1013 0/0:21,0:21:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:28,0:28:70:0,70,1022 0/0:33,0:33:99:0,99,1251 0/0:20,0:20:60:0,60,773 0/0:34,0:34:87:0,87,1305 0/0:23,0:23:60:0,60,900 0/0:28,0:28:84:0,84,1072 0/0:33,0:33:99:0,99,1191 0/0:33,0:33:99:0,99,1189 0/0:30,0:30:72:0,72,1215 0/0:21,0:21:60:0,60,760 0/0:25,0:25:63:0,63,945 0/1:33,40:73:99:1266,0,996 0/0:22,0:22:63:0,63,802 0/0:22,0:22:63:0,63,933 0/0:54,0:54:99:0,114,1710 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,847 0/0:24,0:24:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:33,0:33:93:0,93,1395 0/0:25,0:25:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:34,0:34:93:0,93,1395 0/0:41,0:41:81:0,81,1652 0/0:33,0:33:81:0,81,1395 0/0:59,0:59:99:0,120,1800 0/0:34,0:34:72:0,72,1080 0/0:40,0:40:99:0,99,1485 0/0:52,0:52:99:0,102,1530 0/1:44,39:83:99:1204,0,1372 0/0:39,0:39:99:0,111,1356 0/0:29,0:29:78:0,78,957 0/0:26,0:26:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:24,0:24:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:28,0:28:72:0,72,1019 0/0:35,0:35:64:0,64,1305 0/0:27,0:27:69:0,69,1027 0/0:31,0:31:75:0,75,1125 0/0:33,0:33:75:0,75,1125 0/0:25,0:25:63:0,63,945 0/0:32,0:32:84:0,84,1237 0/0:38,0:38:90:0,90,1350 0/0:29,0:29:66:0,66,985 0/0:34,0:34:61:0,61,972 0/0:29,0:29:84:0,84,984 0/0:26,0:26:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:40,0:40:99:0,105,1575 0/0:29,0:29:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:44,0:44:99:0,120,1800 0/0:31,0:31:93:0,93,1149 0/0:23,0:23:60:0,60,900 0/0:44,0:44:99:0,105,1575 0/0:28,0:28:66:0,66,990 0/0:30,0:30:78:0,78,1132 0/0:21,0:21:60:0,60,724 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,768 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:63:0,63,695 0/0:23,0:23:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:32,0:32:82:0,82,1031 0/0:26,0:26:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,859 0/0:21,0:21:60:0,60,783 0/0:27,0:27:81:0,81,946 0/0:22,0:22:60:0,60,900 0/0:29,0:29:84:0,84,1260 0/0:24,0:24:72:0,72,819 0/0:21,0:21:60:0,60,822 0/0:31,0:31:81:0,81,1215 0/0:23,0:23:63:0,63,938 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,707 0/0:35,0:35:93:0,93,1395 0/0:26,0:26:78:0,78,974 0/0:23,0:23:63:0,63,945 0/0:51,0:51:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:73:0,73,1234 0/0:25,0:25:60:0,60,900 0/0:27,0:27:72:0,72,999 0/0:37,0:37:96:0,96,1440 0/0:26,0:26:64:0,64,1125 0/0:26,0:26:72:0,72,1080 0/0:26,0:26:72:0,72,1080 0/0:22,0:22:60:0,60,684 0/0:30,0:30:87:0,87,946 +20 17596155 rs1132274 C A 149342.00 PASS HWP=0.0;AC=33;culprit=MQ;MQ0=0;ReadPosRankSum=0.306;AN=200;InbreedingCoeff=0.1652;AF=0.22;GQ_STDDEV=159.06;FS=1.188;DP=21042;GQ_MEAN=131.29;POSITIVE_TRAIN_SITE;VQSLOD=5.38;ClippingRankSum=0.067;BaseQRankSum=1.25;MLEAF=0.22;MLEAC=382;MQ=60.0;QD=15.86;DB;MQRankSum=0.142;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:8,10:18:99:308,0,232 0/0:10,0:10:21:0,21,315 0/1:16,13:29:99:325,0,430 0/0:25,0:25:63:0,63,945 0/0:13,0:13:27:0,27,405 0/0:21,0:21:60:0,60,900 0/1:23,17:40:99:412,0,610 0/0:27,0:27:69:0,69,997 0/1:23,12:35:99:346,0,671 0/0:24,0:24:60:0,60,898 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:13,15:28:99:414,0,351 0/1:15,8:23:99:234,0,432 0/0:7,0:7:21:0,21,258 0/1:7,9:16:99:296,0,179 0/0:21,0:21:60:0,60,797 0/1:9,16:25:99:405,0,223 0/0:16,0:16:42:0,42,630 0/0:21,0:21:60:0,60,834 0/0:22,0:22:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:23,0:23:62:0,62,866 0/0:25,0:25:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:18,0:18:22:0,22,495 0/0:23,0:23:63:0,63,803 0/0:23,0:23:60:0,60,900 0/1:7,15:22:99:440,0,167 0/0:27,0:27:66:0,66,990 0/0:24,0:24:63:0,63,908 0/0:23,0:23:63:0,63,824 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,757 0/0:20,0:20:60:0,60,681 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:24,0:24:60:0,60,842 0/0:13,0:13:23:0,23,478 0/0:27,0:27:66:0,66,990 0/0:20,0:20:60:0,60,769 0/0:23,0:23:60:0,60,839 0/0:21,0:21:60:0,60,666 0/0:24,0:24:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:12,0:12:36:0,36,471 0/0:15,0:15:39:0,39,585 0/0:27,0:27:60:0,60,900 0/1:12,6:18:99:126,0,394 0/0:23,0:23:63:0,63,907 0/0:23,0:23:60:0,60,780 0/0:12,0:12:33:0,33,444 0/0:23,0:23:60:0,60,900 0/1:15,14:29:99:391,0,404 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,869 0/1:15,11:26:99:324,0,454 0/0:29,0:29:62:0,62,1035 0/1:14,12:26:99:343,0,318 0/0:24,0:24:66:0,66,858 0/0:8,0:8:21:0,21,300 0/0:21,0:21:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:69:0,69,1035 0/0:21,0:21:60:0,60,718 0/0:13,0:13:23:0,23,501 0/0:22,0:22:60:0,60,795 0/0:15,0:15:24:0,24,360 0/0:21,0:21:60:0,60,900 0/1:4,9:13:99:259,0,119 0/0:25,0:25:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:10,0:10:21:0,21,315 0/1:8,5:13:99:100,0,273 0/0:11,0:11:24:0,24,360 0/0:23,0:23:60:0,60,900 0/1:10,9:19:99:239,0,293 1/1:0,17:17:51:615,51,0 0/1:10,22:32:99:597,0,241 0/1:13,12:25:99:363,0,308 0/0:12,0:12:21:0,21,315 0/0:35,0:35:73:0,73,1265 1/1:0,40:40:99:1371,120,0 1/1:0,21:21:63:713,63,0 0/1:9,12:21:99:333,0,263 0/1:9,9:18:99:212,0,263 0/0:21,0:21:60:0,60,726 0/1:19,9:28:99:219,0,510 0/1:5,5:10:99:136,0,126 1/1:0,28:28:84:1018,84,0 1/1:0,13:13:39:427,39,0 0/1:16,15:31:99:409,0,434 +20 17596206 rs6044909 G C 42164.10 PASS HWP=7.0E-4;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.133;AN=200;InbreedingCoeff=0.1035;AF=0.087;GQ_STDDEV=72.6;FS=0.0;DP=10897;GQ_MEAN=50.67;POSITIVE_TRAIN_SITE;VQSLOD=7.14;ClippingRankSum=0.144;BaseQRankSum=1.04;MLEAF=0.089;MLEAC=155;MQ=60.0;QD=19.32;DB;MQRankSum=0.133;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:5,0:5:12:0,12,179 0/0:10,0:10:21:0,21,315 0/0:12,0:12:30:0,30,450 0/0:11,0:11:27:0,27,405 0/0:7,0:7:21:0,21,238 0/0:14,0:14:33:0,33,495 0/0:15,0:15:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,284 0/0:9,0:9:21:0,21,315 0/0:5,0:5:12:0,12,180 0/0:9,0:9:21:0,21,315 0/0:5,0:5:9:0,9,135 0/0:7,0:7:15:0,15,225 0/0:5,0:5:9:0,9,135 0/1:5,5:10:99:139,0,151 0/0:12,0:12:27:0,27,405 0/0:9,0:9:24:0,24,360 0/0:16,0:16:20:0,20,585 0/0:11,0:11:21:0,21,315 0/0:12,0:12:21:0,21,315 0/0:13,0:13:30:0,30,450 0/0:15,0:15:22:0,22,450 0/0:25,0:25:60:0,60,900 0/0:13,0:13:27:0,27,465 0/0:16,0:16:45:0,45,592 0/0:13,0:13:30:0,30,450 0/0:15,0:15:36:0,36,540 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:12,0:12:30:0,30,450 0/0:23,0:23:63:0,63,824 0/0:24,0:24:60:0,60,900 0/1:4,6:10:99:180,0,130 0/0:10,0:10:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:14,0:14:22:0,22,450 0/0:13,0:13:26:0,26,473 0/0:12,0:12:30:0,30,450 0/0:11,0:11:24:0,24,360 0/0:13,0:13:23:0,23,478 0/0:13,0:13:24:0,24,360 0/0:19,0:19:48:0,48,720 0/0:12,0:12:30:0,30,450 0/0:17,0:17:42:0,42,630 0/0:9,0:9:21:0,21,315 0/0:14,0:14:36:0,36,540 0/0:12,0:12:36:0,36,471 0/0:16,0:16:33:0,33,495 0/0:12,0:12:30:0,30,450 0/0:11,0:11:21:0,21,315 0/0:7,0:7:21:0,21,300 0/0:12,0:12:24:0,24,360 0/0:12,0:12:33:0,33,444 0/0:23,0:23:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:13,0:13:27:0,27,405 0/0:15,0:15:33:0,33,495 0/0:16,0:16:25:0,25,594 0/0:29,0:29:62:0,62,1035 0/0:9,0:9:21:0,21,315 0/0:12,0:12:30:0,30,450 0/0:8,0:8:21:0,21,300 0/0:11,0:11:21:0,21,315 0/0:7,0:7:21:0,21,273 0/0:26,0:26:60:0,60,900 0/0:12,0:12:24:0,24,360 0/0:17,0:17:45:0,45,675 0/0:15,0:15:24:0,24,360 0/0:11,0:11:27:0,27,403 0/0:16,0:16:15:0,15,556 0/0:9,0:9:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:11,0:11:27:0,27,405 0/0:8,0:8:21:0,21,282 0/0:10,0:10:24:0,24,360 0/0:7,0:7:21:0,21,245 0/0:4,0:4:9:0,9,135 0/0:8,0:8:21:0,21,315 0/0:8,0:8:21:0,21,286 0/0:11,0:11:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:12,0:12:21:0,21,390 0/0:7,0:7:21:0,21,256 0/0:5,0:5:15:0,15,203 0/0:4,0:4:12:0,12,151 0/0:35,0:35:73:0,73,1265 0/0:11,0:11:27:0,27,405 0/0:4,0:4:6:0,6,90 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:11,0:11:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:4,0:4:9:0,9,130 0/0:13,0:13:30:0,30,450 0/0:5,0:5:5:0,5,135 0/0:9,0:9:21:0,21,315 +20 17596216 rs74955526 A C 18344.60 PASS HWP=0.7359;AC=6;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.322;AN=200;InbreedingCoeff=-0.0105;AF=0.05;GQ_STDDEV=51.38;FS=0.0;DP=9608;GQ_MEAN=37.21;VQSLOD=5.72;ClippingRankSum=0.196;BaseQRankSum=2.02;MLEAF=0.051;MLEAC=88;MQ=60.0;QD=17.34;DB;MQRankSum=0.101;CCC=1734;NCC=3 GT:AD:DP:GQ:PL 0/0:5,0:5:12:0,12,179 0/0:10,0:10:21:0,21,315 0/0:12,0:12:30:0,30,450 0/0:11,0:11:27:0,27,405 0/0:7,0:7:21:0,21,238 0/0:14,0:14:33:0,33,495 0/0:15,0:15:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,284 0/0:9,0:9:21:0,21,315 0/0:5,0:5:12:0,12,180 0/0:9,0:9:18:0,18,270 0/0:5,0:5:9:0,9,135 0/1:2,5:7:56:157,0,56 0/0:5,0:5:9:0,9,135 0/0:7,0:7:12:0,12,180 0/0:12,0:12:27:0,27,405 0/0:9,0:9:24:0,24,360 0/1:6,10:16:99:348,0,173 0/1:7,4:11:99:117,0,215 0/0:12,0:12:21:0,21,315 0/0:13,0:13:30:0,30,450 0/0:15,0:15:22:0,22,450 0/0:17,0:17:36:0,36,540 0/1:6,7:13:99:241,0,180 0/0:16,0:16:45:0,45,592 0/0:12,0:12:30:0,30,450 0/0:15,0:15:36:0,36,540 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/1:4,4:8:99:151,0,131 0/0:12,0:12:30:0,30,450 0/0:23,0:23:63:0,63,824 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,275 0/1:4,7:11:99:267,0,124 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:14,0:14:22:0,22,450 0/0:13,0:13:26:0,26,473 0/0:12,0:12:30:0,30,450 0/0:8,0:8:21:0,21,299 0/0:13,0:13:23:0,23,478 0/0:13,0:13:24:0,24,360 0/0:19,0:19:48:0,48,720 0/0:12,0:12:30:0,30,450 0/0:17,0:17:42:0,42,630 0/0:9,0:9:21:0,21,315 0/0:14,0:14:36:0,36,540 0/0:12,0:12:36:0,36,471 0/0:16,0:16:33:0,33,495 0/0:12,0:12:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:7,0:7:21:0,21,300 0/0:12,0:12:24:0,24,360 0/0:12,0:12:33:0,33,444 0/0:23,0:23:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:13,0:13:27:0,27,405 0/0:15,0:15:33:0,33,495 0/0:16,0:16:25:0,25,594 0/0:23,0:23:27:0,27,761 0/0:9,0:9:21:0,21,315 0/0:12,0:12:30:0,30,450 0/0:5,0:5:12:0,12,180 0/0:6,0:6:12:0,12,180 0/0:7,0:7:21:0,21,273 0/0:17,0:17:39:0,39,585 0/0:9,0:9:21:0,21,315 0/0:17,0:17:45:0,45,675 0/0:15,0:15:24:0,24,360 0/0:11,0:11:27:0,27,403 0/0:11,0:11:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:11,0:11:27:0,27,405 0/0:8,0:8:21:0,21,282 0/0:10,0:10:24:0,24,360 0/0:7,0:7:21:0,21,245 0/0:4,0:4:9:0,9,135 0/0:7,0:7:15:0,15,225 0/0:6,0:6:9:0,9,195 0/0:11,0:11:27:0,27,405 0/0:7,0:7:18:0,18,270 0/0:12,0:12:21:0,21,390 0/0:7,0:7:6:0,6,90 0/0:5,0:5:15:0,15,203 0/0:4,0:4:12:0,12,151 0/0:35,0:35:73:0,73,1265 0/0:11,0:11:27:0,27,405 0/0:4,0:4:6:0,6,90 0/0:9,0:9:21:0,21,315 0/0:8,0:8:12:0,12,180 0/0:11,0:11:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:4,0:4:9:0,9,130 0/0:13,0:13:30:0,30,450 0/0:5,0:5:5:0,5,135 0/0:9,0:9:21:0,21,315 +20 17596219 rs12479820 C T 52506.40 PASS HWP=0.0;AC=24;culprit=MQ;MQ0=0;ReadPosRankSum=0.387;AN=200;InbreedingCoeff=0.1857;AF=0.179;GQ_STDDEV=58.37;FS=1.254;DP=9358;GQ_MEAN=45.51;POSITIVE_TRAIN_SITE;VQSLOD=4.9;ClippingRankSum=0.156;BaseQRankSum=1.58;MLEAF=0.191;MLEAC=331;MQ=60.0;QD=17.77;DB;MQRankSum=0.0;CCC=1730;NCC=5 GT:AD:DP:GQ:PL 0/0:5,0:5:0:0,0,28 0/0:7,0:7:18:0,18,270 0/1:8,4:12:99:114,0,247 0/0:11,0:11:27:0,27,405 0/0:7,0:7:21:0,21,238 0/0:14,0:14:33:0,33,495 0/1:7,7:14:99:219,0,211 0/0:10,0:10:24:0,24,360 0/1:7,3:10:88:88,0,213 0/0:8,0:8:21:0,21,284 0/0:9,0:9:21:0,21,315 0/0:5,0:5:12:0,12,180 0/1:5,5:10:99:167,0,147 0/0:4,0:4:0:0,0,9 0/0:5,0:5:12:0,12,180 0/0:5,0:5:0:0,0,27 0/0:7,0:7:12:0,12,180 0/1:6,6:12:99:165,0,176 0/0:9,0:9:24:0,24,360 0/0:14,0:14:30:0,30,450 0/0:9,0:9:27:0,27,339 0/0:12,0:12:21:0,21,315 0/0:13,0:13:30:0,30,450 0/0:15,0:15:22:0,22,450 0/0:17,0:17:36:0,36,540 0/0:15,0:15:39:0,39,559 0/0:16,0:16:45:0,45,592 0/0:12,0:12:30:0,30,450 0/0:15,0:15:36:0,36,540 0/0:8,0:8:21:0,21,315 0/1:3,7:10:44:212,0,44 0/0:6,0:6:15:0,15,225 0/0:12,0:12:30:0,30,450 0/0:23,0:23:63:0,63,824 0/0:21,0:21:42:0,42,630 0/0:8,0:8:21:0,21,275 0/0:9,0:9:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:14,0:14:22:0,22,450 0/0:13,0:13:26:0,26,473 0/0:12,0:12:30:0,30,450 0/0:8,0:8:21:0,21,299 0/0:13,0:13:23:0,23,478 0/0:13,0:13:24:0,24,360 0/0:19,0:19:48:0,48,720 0/0:12,0:12:30:0,30,450 0/0:17,0:17:42:0,42,630 0/0:9,0:9:21:0,21,315 0/0:14,0:14:15:0,15,414 0/0:12,0:12:36:0,36,471 0/0:16,0:16:33:0,33,495 0/0:12,0:12:30:0,30,450 0/1:3,4:7:78:131,0,78 0/0:7,0:7:21:0,21,300 0/0:12,0:12:24:0,24,360 0/0:12,0:12:33:0,33,444 0/0:23,0:23:60:0,60,900 0/1:5,5:10:99:138,0,146 0/0:13,0:13:27:0,27,405 0/0:15,0:15:33:0,33,495 0/1:8,8:16:99:252,0,215 0/0:23,0:23:27:0,27,761 0/1:5,5:10:99:152,0,131 0/0:12,0:12:30:0,30,450 0/0:5,0:5:12:0,12,180 0/0:6,0:6:12:0,12,180 0/0:7,0:7:21:0,21,273 0/0:17,0:17:39:0,39,585 0/0:9,0:9:21:0,21,315 0/0:17,0:17:45:0,45,675 0/0:15,0:15:24:0,24,360 0/0:11,0:11:27:0,27,403 0/0:11,0:11:30:0,30,450 0/0:7,0:7:18:0,18,270 0/0:3,0:3:6:0,6,90 0/0:11,0:11:27:0,27,405 0/1:2,6:8:49:199,0,49 0/0:10,0:10:24:0,24,360 0/0:7,0:7:21:0,21,245 0/0:4,0:4:9:0,9,135 0/0:7,0:7:0:0,0,180 0/0:6,0:6:9:0,9,195 0/0:11,0:11:27:0,27,405 0/1:4,3:7:92:92,0,120 1/1:0,11:11:33:409,33,0 0/1:5,3:8:94:94,0,144 0/0:5,0:5:15:0,15,203 0/0:4,0:4:12:0,12,151 0/0:35,0:35:73:0,73,1265 1/1:0,11:11:33:434,33,0 1/1:0,5:5:15:195,15,0 0/1:2,6:8:47:163,0,47 0/0:8,0:8:0:0,0,143 0/0:11,0:11:24:0,24,360 0/1:6,3:9:92:92,0,168 0/0:4,0:4:9:0,9,130 1/1:0,12:12:36:445,36,0 0/0:5,0:5:0:0,0,4 0/1:7,4:11:99:112,0,208 +20 17596544 rs140440284 G A 1777.38 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.13;AN=200;InbreedingCoeff=-0.004;AF=0.003448;GQ_STDDEV=29.29;FS=0.856;DP=20752;GQ_MEAN=59.9;POSITIVE_TRAIN_SITE;VQSLOD=3.75;ClippingRankSum=-0.502;BaseQRankSum=-0.933;MLEAF=0.003448;MLEAC=6;MQ=60.0;QD=11.77;DB;MQRankSum=0.551;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,788 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:20,0:20:60:0,60,702 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,858 0/0:25,0:25:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:11,0:11:33:0,33,372 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,900 0/0:9,0:9:24:0,24,360 0/0:20,0:20:60:0,60,683 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:63:0,63,839 0/0:21,0:21:60:0,60,783 0/0:21,0:21:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:32,0:32:61:0,61,1059 0/0:26,0:26:60:0,60,871 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:27,0:27:72:0,72,975 0/0:21,0:21:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:38,0:38:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,803 0/0:22,0:22:63:0,63,823 0/1:13,17:30:99:445,0,432 0/0:30,0:30:60:0,60,900 0/0:14,0:14:35:0,35,458 0/0:9,0:9:27:0,27,328 0/0:17,0:17:34:0,34,659 0/0:27,0:27:60:0,60,900 0/0:25,0:25:65:0,65,1080 0/0:26,0:26:60:0,60,900 0/0:19,0:19:42:0,42,630 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,861 0/0:30,0:30:61:0,61,990 0/0:27,0:27:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:10,0:10:22:0,22,360 0/0:21,0:21:60:0,60,765 0/0:22,0:22:60:0,60,900 0/0:16,0:16:36:0,36,540 0/0:32,0:32:72:0,72,1080 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:17,0:17:22:0,22,546 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:21,0:21:60:0,60,748 0/0:22,0:22:60:0,60,900 0/0:20,0:20:48:0,48,720 0/0:22,0:22:63:0,63,763 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,760 0/0:22,0:22:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:29,0:29:63:0,63,945 0/0:14,0:14:25:0,25,521 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,727 0/0:21,0:21:60:0,60,856 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,705 0/0:12,0:12:27:0,27,405 0/0:9,0:9:25:0,25,364 0/0:14,0:14:29:0,29,530 0/0:14,0:14:26:0,26,456 0/0:20,0:20:60:0,60,688 0/0:9,0:9:27:0,27,350 0/0:18,0:18:48:0,48,664 0/0:31,0:31:84:0,84,1071 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,699 0/0:32,0:32:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:22,0:22:60:0,60,866 0/0:21,0:21:60:0,60,900 0/0:27,0:27:81:0,81,991 0/0:23,0:23:69:0,69,822 0/0:16,0:16:39:0,39,547 0/0:24,0:24:66:0,66,867 0/0:20,0:20:60:0,60,735 0/0:23,0:23:63:0,63,816 +20 17596587 rs2229893 G A 13755.70 PASS HWP=0.3705;AC=6;culprit=MQ;MQ0=0;ReadPosRankSum=0.193;AN=200;InbreedingCoeff=0.0589;AF=0.016;GQ_STDDEV=79.13;FS=3.311;DP=22025;GQ_MEAN=72.39;POSITIVE_TRAIN_SITE;VQSLOD=3.13;ClippingRankSum=0.14;BaseQRankSum=0.529;MLEAF=0.016;MLEAC=27;MQ=60.0;QD=12.55;DB;MQRankSum=-0.247;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,788 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:20,0:20:60:0,60,702 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,858 0/0:25,0:25:60:0,60,900 0/1:34,24:58:99:624,0,878 0/0:20,0:20:60:0,60,750 0/0:10,0:10:24:0,24,342 0/1:18,13:31:99:368,0,475 0/0:21,0:21:60:0,60,696 0/0:23,0:23:63:0,63,711 0/0:23,0:23:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:23,0:23:63:0,63,839 0/0:21,0:21:60:0,60,783 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:32,0:32:61:0,61,1059 0/0:26,0:26:60:0,60,871 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:27,0:27:72:0,72,975 0/0:21,0:21:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:38,0:38:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,803 0/0:22,0:22:63:0,63,823 0/0:25,0:25:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:18,0:18:27:0,27,405 0/0:21,0:21:60:0,60,775 0/0:27,0:27:60:0,60,900 0/0:25,0:25:65:0,65,1080 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,861 0/0:30,0:30:61:0,61,990 0/0:27,0:27:63:0,63,945 0/0:24,0:24:66:0,66,990 0/0:10,0:10:22:0,22,360 0/0:24,0:24:60:0,60,900 0/0:29,0:29:47:0,47,872 0/0:16,0:16:36:0,36,540 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:57:0,57,855 0/0:27,0:27:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,748 0/0:22,0:22:60:0,60,900 0/0:13,0:13:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:16,0:16:42:0,42,630 0/0:22,0:22:60:0,60,771 0/0:25,0:25:34:0,34,742 0/0:21,0:21:60:0,60,856 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,705 0/0:9,0:9:21:0,21,315 0/0:9,0:9:25:0,25,364 0/0:13,0:13:26:0,26,450 0/0:14,0:14:26:0,26,456 0/0:20,0:20:60:0,60,688 0/0:21,0:21:60:0,60,740 0/0:25,0:25:63:0,63,945 0/1:37,30:67:99:789,0,954 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,699 0/0:32,0:32:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:22,0:22:60:0,60,866 0/0:9,0:9:21:0,21,315 1/1:0,47:47:99:1499,141,0 0/1:28,26:54:99:644,0,651 0/0:16,0:16:39:0,39,547 0/0:24,0:24:63:0,63,919 0/0:22,0:22:51:0,51,763 0/0:24,0:24:43:0,43,694 +20 17596673 rs113759416 C T 908.39 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.622;AN=200;InbreedingCoeff=-0.0038;AF=0.001149;GQ_STDDEV=29.67;FS=0.0;DP=15695;GQ_MEAN=41.34;POSITIVE_TRAIN_SITE;VQSLOD=3.75;ClippingRankSum=1.33;BaseQRankSum=-3.282;MLEAF=0.001149;MLEAC=2;MQ=59.11;QD=12.98;DB;MQRankSum=-0.462;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:10,0:10:24:0,24,360 0/0:26,0:26:60:0,60,900 0/0:11,0:11:24:0,24,360 0/0:22,0:22:60:0,60,900 0/0:13,0:13:27:0,27,405 0/0:11,0:11:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:14,0:14:33:0,33,495 0/0:12,0:12:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:14,0:14:22:0,22,405 0/0:23,0:23:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:2,0:2:6:0,6,72 0/0:12,0:12:23:0,23,451 0/0:10,0:10:21:0,21,315 0/0:9,0:9:21:0,21,311 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:12,0:12:21:0,21,315 0/0:12,0:12:21:0,21,315 0/0:17,0:17:21:0,21,315 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:26,0:26:60:0,60,871 0/0:17,0:17:42:0,42,630 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:13,0:13:27:0,27,405 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:38,0:38:69:0,69,1035 0/0:12,0:12:21:0,21,315 0/0:16,0:16:27:0,27,405 0/0:10,0:10:20:0,20,315 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:12,0:12:26:0,26,495 0/0:10,0:10:24:0,24,360 0/0:10,0:10:21:0,21,315 0/0:15,0:15:33:0,33,495 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:11,0:11:27:0,27,405 0/0:14,0:14:39:0,39,464 0/0:16,0:16:33:0,33,495 0/1:13,13:26:99:370,0,442 0/0:11,0:11:24:0,24,350 0/0:9,0:9:21:0,21,315 0/0:11,0:11:27:0,27,405 0/0:10,0:10:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:20,0:20:45:0,45,675 0/0:23,0:23:60:0,60,900 0/0:14,0:14:25:0,25,450 0/0:12,0:12:30:0,30,376 0/0:26,0:26:60:0,60,900 0/0:13,0:13:20:0,20,495 0/0:11,0:11:24:0,24,356 0/0:12,0:12:24:0,24,360 0/0:4,0:4:6:0,6,90 0/0:9,0:9:21:0,21,315 0/0:17,0:17:42:0,42,630 0/0:10,0:10:24:0,24,360 0/0:15,0:15:30:0,30,540 0/0:8,0:8:21:0,21,315 0/0:29,0:29:63:0,63,945 0/0:11,0:11:27:0,27,405 0/0:11,0:11:30:0,30,450 0/0:9,0:9:24:0,24,356 0/0:9,0:9:21:0,21,315 0/0:13,0:13:27:0,27,405 0/0:11,0:11:20:0,20,315 0/0:9,0:9:21:0,21,315 0/0:4,0:4:9:0,9,133 0/0:11,0:11:15:0,15,270 0/0:7,0:7:21:0,21,261 0/0:13,0:13:20:0,20,390 0/0:11,0:11:27:0,27,405 0/0:11,0:11:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:24,0:24:63:0,63,945 0/0:32,0:32:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:18,0:18:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:12,0:12:27:0,27,405 0/0:19,0:19:36:0,36,540 0/0:2,0:2:6:0,6,85 0/0:13,0:13:28:0,28,450 0/0:9,0:9:22:0,22,344 0/0:10,0:10:24:0,24,360 +20 17597331 rs911347 C T 697330.00 PASS HWP=0.0012;AC=152;culprit=FS;MQ0=0;ReadPosRankSum=0.121;AN=200;InbreedingCoeff=0.1078;AF=0.583;GQ_STDDEV=321.99;FS=0.0;DP=35686;GQ_MEAN=309.75;POSITIVE_TRAIN_SITE;VQSLOD=6.87;ClippingRankSum=-0.04;BaseQRankSum=-3.647;MLEAF=0.584;MLEAC=1017;MQ=59.7;QD=24.13;DB;MQRankSum=0.064;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:21,27:48:99:810,0,679 1/1:0,37:37:99:1322,111,0 0/1:32,22:54:99:608,0,1053 1/1:0,56:56:99:2020,168,0 1/1:0,48:48:99:1747,144,0 1/1:0,57:57:99:2019,171,0 0/1:25,30:55:99:928,0,873 1/1:0,47:47:99:1702,141,0 0/1:27,25:52:99:779,0,850 1/1:0,43:43:99:1563,129,0 1/1:1,27:28:81:1019,81,0 1/1:1,54:55:99:1938,162,0 0/1:31,23:54:99:714,0,1077 0/1:30,25:55:99:756,0,975 0/0:20,0:20:60:0,60,739 0/1:20,10:30:99:263,0,680 0/1:13,17:30:99:539,0,417 0/1:14,12:26:99:365,0,461 1/1:0,25:25:75:906,75,0 0/1:11,13:24:99:410,0,359 0/0:16,0:16:36:0,36,585 1/1:0,26:26:78:956,78,0 1/1:0,21:21:63:774,63,0 1/1:0,17:17:51:607,51,0 1/1:0,20:20:60:765,60,0 0/0:28,0:28:71:0,71,965 1/1:0,22:22:66:820,66,0 1/1:0,39:39:99:1396,117,0 1/1:0,63:63:99:2239,189,0 1/1:0,74:74:99:2646,223,0 0/1:19,27:46:99:808,0,622 0/1:22,16:38:99:500,0,796 1/1:0,58:58:99:2136,175,0 1/1:0,90:90:99:3246,271,0 1/1:0,57:57:99:2086,171,0 0/1:13,12:25:99:350,0,412 0/0:28,0:28:78:0,78,1170 1/1:0,22:22:66:805,66,0 1/1:0,35:35:99:1315,105,0 1/1:0,43:43:99:1566,128,0 1/1:0,28:28:84:1030,84,0 1/1:0,21:21:63:773,63,0 1/1:0,23:23:69:839,69,0 0/1:21,11:32:99:331,0,710 1/1:0,30:30:90:1116,90,0 1/1:0,32:32:96:1134,96,0 1/1:0,29:29:87:1062,87,0 1/1:0,28:28:84:998,84,0 1/1:0,50:50:99:1875,150,0 1/1:0,63:63:99:2335,189,0 1/1:0,32:32:96:1191,96,0 0/1:13,17:30:99:551,0,430 0/1:10,10:20:99:311,0,323 0/1:13,16:29:99:491,0,448 1/1:0,46:46:99:1622,138,0 0/1:19,15:34:99:439,0,603 1/1:0,41:41:99:1546,123,0 1/1:0,41:41:99:1568,123,0 0/1:14,15:29:99:462,0,453 1/1:0,54:54:99:2042,163,0 1/1:0,19:19:57:710,57,0 0/1:5,13:18:99:426,0,145 1/1:0,89:89:99:3235,268,0 0/1:9,12:21:99:371,0,274 1/1:0,29:29:87:1063,87,0 1/1:0,21:21:63:778,63,0 1/1:0,21:21:63:769,63,0 1/1:0,25:25:75:929,75,0 0/1:24,29:53:99:931,0,748 1/1:0,24:24:72:887,72,0 1/1:0,41:41:99:1496,123,0 1/1:0,27:27:81:1022,81,0 1/1:0,36:36:99:1304,108,0 1/1:0,22:22:66:808,66,0 1/1:0,31:31:93:1159,93,0 1/1:0,19:19:57:698,57,0 1/1:0,48:48:99:1736,144,0 0/1:21,19:40:99:581,0,771 1/1:0,20:20:60:761,60,0 1/1:0,34:34:99:1267,102,0 1/1:0,20:20:60:739,60,0 0/1:9,18:27:99:574,0,288 1/1:0,23:23:69:856,69,0 1/1:0,39:39:99:1456,117,0 0/1:9,12:21:99:390,0,292 0/0:36,0:36:98:0,98,1426 0/1:18,19:37:99:581,0,571 1/1:0,38:38:99:1403,114,0 1/1:0,29:29:87:1071,87,0 1/1:0,79:79:99:2913,238,0 0/0:35,0:35:67:0,67,1418 0/0:38,0:38:99:0,111,1665 0/1:13,16:29:99:499,0,446 0/1:14,15:29:99:462,0,454 1/1:0,21:21:63:780,63,0 0/1:14,15:29:99:435,0,499 0/1:10,7:17:99:211,0,367 0/0:39,0:39:99:0,114,1710 0/1:11,8:19:99:230,0,382 0/1:13,12:25:99:366,0,451 +20 17597361 rs911348 A G 1987890.00 PASS HWP=1.0;AC=200;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.226;AN=200;InbreedingCoeff=-0.0116;AF=0.989;GQ_STDDEV=144.31;FS=0.0;DP=59833;GQ_MEAN=219.21;POSITIVE_TRAIN_SITE;VQSLOD=4.25;ClippingRankSum=0.63;BaseQRankSum=0.812;MLEAF=0.989;MLEAC=1720;MQ=59.66;QD=33.32;DB;MQRankSum=-0.118;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,74:74:99:2532,222,0 1/1:0,59:59:99:2004,177,0 1/1:0,85:85:99:2813,255,0 1/1:0,99:99:99:3377,298,0 1/1:0,83:83:99:2846,249,0 1/1:0,92:92:99:3131,276,0 1/1:0,83:83:99:2870,250,0 1/1:0,69:69:99:2388,207,0 1/1:0,75:75:99:2601,226,0 1/1:0,77:77:99:2698,232,0 1/1:0,64:64:99:2255,192,0 1/1:0,91:91:99:3066,273,0 1/1:0,81:81:99:2766,243,0 1/1:0,86:86:99:2904,258,0 1/1:0,31:31:96:1223,96,0 1/1:0,53:53:99:1684,158,0 1/1:0,43:43:99:1356,129,0 1/1:0,39:39:99:1343,117,0 1/1:0,39:39:99:1307,117,0 1/1:0,48:48:99:1577,144,0 1/1:0,36:36:99:1136,108,0 1/1:1,44:45:99:1387,109,0 1/1:0,36:36:99:1203,108,0 1/1:0,33:33:99:1169,99,0 1/1:0,46:46:99:1573,138,0 1/1:0,36:36:99:1129,107,0 1/1:0,32:32:95:1015,95,0 1/1:0,53:53:99:1708,159,0 1/1:0,89:89:99:2959,267,0 1/1:0,122:122:99:3977,363,0 1/1:0,80:80:99:2581,241,0 1/1:0,71:71:99:2401,213,0 1/1:0,83:83:99:2707,248,0 1/1:0,123:123:99:4061,369,0 1/1:0,87:87:99:2905,261,0 1/1:0,48:48:99:1576,144,0 1/1:0,53:53:99:2319,172,0 1/1:0,47:47:99:1589,141,0 1/1:0,44:44:99:1349,130,0 1/1:0,56:56:99:1801,168,0 1/1:0,37:37:99:1105,111,0 1/1:0,22:22:66:704,66,0 1/1:0,28:28:84:858,84,0 1/1:1,45:46:99:1449,128,0 1/1:0,45:45:99:1465,135,0 1/1:0,42:42:99:1342,126,0 1/1:0,35:35:99:1163,105,0 1/1:0,35:35:99:1045,104,0 1/1:0,86:86:99:2902,258,0 1/1:0,102:102:99:3350,305,0 1/1:0,38:38:99:1239,114,0 1/1:0,30:30:90:949,90,0 1/1:1,26:27:48:830,48,0 1/1:0,47:47:99:1607,141,0 1/1:0,82:82:99:2694,246,0 1/1:0,31:31:93:934,93,0 1/1:0,58:58:99:1835,174,0 1/1:0,47:47:99:1476,141,0 1/1:1,42:43:99:1339,119,0 1/1:0,77:77:99:2632,231,0 1/1:0,36:36:99:1116,108,0 1/1:0,27:27:81:845,81,0 1/1:0,113:113:99:3800,339,0 1/1:0,30:30:90:947,90,0 1/1:0,42:42:99:1366,126,0 1/1:0,42:42:99:1436,126,0 1/1:0,30:30:89:956,89,0 1/1:0,38:38:99:1307,114,0 1/1:0,104:104:99:3462,312,0 1/1:0,43:43:99:1472,129,0 1/1:0,62:62:99:1996,185,0 1/1:0,52:52:99:1826,156,0 1/1:1,64:65:99:2130,189,0 1/1:0,36:36:99:1231,108,0 1/1:0,53:53:99:1786,161,0 1/1:0,32:32:96:1091,96,0 1/1:0,59:59:99:1938,177,0 1/1:0,57:57:99:1969,171,0 1/1:0,44:44:99:1447,132,0 1/1:0,53:53:99:1718,158,0 1/1:0,38:38:99:1275,113,0 1/1:0,33:33:99:1140,99,0 1/1:0,32:32:96:1057,96,0 1/1:0,57:57:99:1917,171,0 1/1:0,38:38:99:1333,114,0 1/1:0,61:61:99:1980,183,0 1/1:0,60:60:99:1890,180,0 1/1:0,74:74:99:2476,222,0 1/1:0,47:47:99:1601,141,0 1/1:1,92:93:99:3036,251,0 1/1:0,88:88:99:2950,264,0 1/1:0,78:78:99:2545,234,0 1/1:0,42:42:99:1398,126,0 1/1:0,41:41:99:1421,123,0 1/1:0,55:55:99:1903,165,0 1/1:0,55:55:99:1874,165,0 1/1:0,25:25:75:813,75,0 1/1:0,57:57:99:1936,171,0 1/1:0,32:32:96:1043,96,0 1/1:0,52:52:99:1747,156,0 +20 17597369 rs56102376 G A 59308.70 PASS HWP=0.0996;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=0.702;AN=200;InbreedingCoeff=0.0769;AF=0.032;GQ_STDDEV=219.89;FS=0.873;DP=43666;GQ_MEAN=142.52;POSITIVE_TRAIN_SITE;VQSLOD=5.19;ClippingRankSum=0.139;BaseQRankSum=3.43;MLEAF=0.032;MLEAC=55;MQ=59.75;QD=15.36;DB;MQRankSum=0.65;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:53,0:53:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:41,0:41:93:0,93,1395 0/0:47,0:47:99:0,106,1710 0/0:60,0:60:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/0:40,0:40:87:0,87,1305 0/0:61,0:61:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:51,0:51:90:0,90,1800 0/0:48,0:48:99:0,108,1620 0/0:80,0:80:99:0,120,1800 0/0:51,0:51:99:0,117,1800 0/1:14,16:30:99:451,0,344 0/0:50,0:50:99:0,120,1800 0/0:35,0:35:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:34,0:34:66:0,66,990 0/0:52,0:52:99:0,120,1800 0/0:27,0:27:60:0,60,900 0/0:48,0:48:99:0,120,1800 0/0:34,0:34:75:0,75,1290 0/0:33,0:33:81:0,81,1215 0/0:44,0:44:99:0,109,1647 0/0:30,0:30:63:0,63,945 0/0:30,0:30:66:0,66,973 0/0:33,0:33:63:0,63,945 0/0:49,0:49:99:0,120,1420 0/0:67,0:67:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/0:74,0:74:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:57,0:57:99:0,108,1620 0/0:54,0:54:99:0,120,1800 0/0:34,0:34:81:0,81,1215 0/1:28,31:59:99:919,0,811 0/0:30,0:30:60:0,60,900 0/0:38,0:38:96:0,96,1165 0/0:36,0:36:75:0,75,1125 0/0:34,0:34:63:0,63,945 0/0:23,0:23:63:0,63,852 0/0:28,0:28:66:0,66,925 0/0:39,0:39:68:0,68,1124 0/0:37,0:37:67:0,67,1219 0/0:28,0:28:69:0,69,860 0/0:32,0:32:72:0,72,1080 0/0:36,0:36:62:0,62,1241 0/0:43,0:43:99:0,105,1575 0/0:71,0:71:99:0,120,1800 0/0:32,0:32:61:0,61,1000 0/0:26,0:26:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:41,0:41:87:0,87,1305 0/0:42,0:42:93:0,93,1395 0/0:29,0:29:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:31,0:31:65:0,65,901 0/0:35,0:35:78:0,78,1253 0/0:58,0:58:99:0,117,1755 0/0:26,0:26:69:0,69,820 0/0:25,0:25:63:0,63,945 0/0:88,0:88:99:0,120,1800 0/0:30,0:30:75:0,75,1111 0/0:31,0:31:66:0,66,990 0/0:37,0:37:84:0,84,1260 0/0:29,0:29:67:0,67,940 0/0:38,0:38:77:0,77,1232 0/0:55,0:55:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:34,0:34:78:0,78,1170 0/0:33,0:33:69:0,69,1035 0/0:45,0:45:99:0,99,1485 0/0:38,0:38:69:0,69,1080 0/0:32,0:32:65:0,65,990 0/0:31,0:31:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:38,0:38:69:0,69,1035 0/0:34,0:34:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:33,0:33:81:0,81,1088 0/0:38,0:38:87:0,87,1305 0/0:29,0:29:60:0,60,900 0/0:45,0:45:99:0,116,1646 0/0:63,0:63:99:0,120,1800 0/0:40,0:40:87:0,87,1305 0/0:32,0:32:84:0,84,1260 0/0:75,0:75:68:0,68,1800 0/0:55,0:55:99:0,105,1575 0/0:45,0:45:96:0,96,1440 0/0:29,0:29:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:57,0:57:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:26,0:26:66:0,66,942 0/0:45,0:45:99:0,102,1530 0/0:27,0:27:63:0,63,945 0/0:47,0:47:93:0,93,1395 +20 17597482 rs41290441 G A 164409.00 PASS HWP=0.3147;AC=5;culprit=FS;MQ0=0;ReadPosRankSum=0.27;AN=200;InbreedingCoeff=0.0425;AF=0.066;GQ_STDDEV=452.51;FS=0.66;DP=47117;GQ_MEAN=243.83;POSITIVE_TRAIN_SITE;VQSLOD=5.45;ClippingRankSum=0.193;BaseQRankSum=-3.513;MLEAF=0.066;MLEAC=114;MQ=59.62;QD=14.06;DB;MQRankSum=0.329;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:53,0:53:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:41,0:41:93:0,93,1395 0/0:47,0:47:99:0,106,1710 0/0:60,0:60:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/0:40,0:40:87:0,87,1305 0/0:61,0:61:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:51,0:51:90:0,90,1800 0/0:48,0:48:99:0,108,1620 0/0:80,0:80:99:0,120,1800 0/0:51,0:51:99:0,117,1800 0/0:23,0:23:60:0,60,721 0/0:50,0:50:99:0,120,1800 0/0:35,0:35:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:34,0:34:66:0,66,990 0/1:46,36:82:99:951,0,1394 0/0:27,0:27:60:0,60,900 0/1:23,45:68:99:1322,0,656 0/0:34,0:34:75:0,75,1290 0/0:33,0:33:81:0,81,1215 0/0:44,0:44:99:0,109,1647 0/0:30,0:30:63:0,63,945 0/0:30,0:30:66:0,66,973 0/0:33,0:33:63:0,63,945 0/0:49,0:49:99:0,120,1420 0/0:67,0:67:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/1:57,54:111:99:1616,0,1820 0/1:74,60:134:99:1681,0,2437 0/0:57,0:57:99:0,108,1620 0/0:54,0:54:99:0,120,1800 0/0:34,0:34:81:0,81,1215 0/0:34,0:34:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:38,0:38:96:0,96,1165 0/0:36,0:36:75:0,75,1125 0/0:34,0:34:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:28,0:28:66:0,66,925 0/0:39,0:39:68:0,68,1124 0/0:37,0:37:67:0,67,1219 0/0:28,0:28:69:0,69,860 0/0:32,0:32:72:0,72,1080 0/0:36,0:36:62:0,62,1241 0/0:43,0:43:99:0,105,1575 0/0:71,0:71:99:0,120,1800 0/0:32,0:32:61:0,61,1000 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:41,0:41:87:0,87,1305 0/0:42,0:42:93:0,93,1395 0/0:29,0:29:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:31,0:31:65:0,65,901 0/0:35,0:35:78:0,78,1253 0/0:58,0:58:99:0,117,1755 0/0:26,0:26:69:0,69,820 0/0:24,0:24:60:0,60,784 0/0:88,0:88:99:0,120,1800 0/0:30,0:30:75:0,75,1111 0/0:31,0:31:66:0,66,990 0/0:37,0:37:84:0,84,1260 0/0:29,0:29:67:0,67,940 0/1:27,29:56:99:817,0,880 0/0:55,0:55:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:34,0:34:78:0,78,1170 0/0:33,0:33:69:0,69,1035 0/0:45,0:45:99:0,99,1485 0/0:38,0:38:69:0,69,1080 0/0:32,0:32:65:0,65,990 0/0:31,0:31:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:38,0:38:69:0,69,1035 0/0:34,0:34:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:33,0:33:81:0,81,1088 0/0:38,0:38:87:0,87,1305 0/0:29,0:29:60:0,60,900 0/0:45,0:45:99:0,116,1646 0/0:63,0:63:99:0,120,1800 0/0:40,0:40:87:0,87,1305 0/0:32,0:32:84:0,84,1260 0/0:75,0:75:68:0,68,1800 0/0:55,0:55:99:0,105,1575 0/0:45,0:45:96:0,96,1440 0/0:29,0:29:60:0,60,900 0/0:29,0:29:63:0,63,945 0/0:57,0:57:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:26,0:26:66:0,66,942 0/0:45,0:45:99:0,102,1530 0/0:27,0:27:63:0,63,945 0/0:47,0:47:93:0,93,1395 +20 17597491 rs8183329 C T 32783.60 PASS HWP=0.3705;AC=6;culprit=FS;MQ0=0;ReadPosRankSum=0.842;AN=200;InbreedingCoeff=0.0595;AF=0.016;GQ_STDDEV=191.88;FS=0.0;DP=40853;GQ_MEAN=124.08;POSITIVE_TRAIN_SITE;VQSLOD=7.05;ClippingRankSum=-0.008;BaseQRankSum=-3.826;MLEAF=0.016;MLEAC=27;MQ=59.8;QD=13.38;DB;MQRankSum=0.46;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:53,0:53:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,102,1530 0/0:41,0:41:93:0,93,1395 0/0:47,0:47:99:0,106,1710 0/0:60,0:60:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/0:40,0:40:87:0,87,1305 0/0:61,0:61:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:51,0:51:90:0,90,1800 0/0:48,0:48:99:0,108,1620 0/1:64,49:113:99:1394,0,2115 0/0:51,0:51:99:0,117,1800 0/0:23,0:23:60:0,60,721 0/1:41,34:75:99:1008,0,1332 0/0:35,0:35:60:0,60,900 0/0:37,0:37:84:0,84,1260 0/0:34,0:34:66:0,66,990 0/0:38,0:38:90:0,90,1290 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:34,0:34:75:0,75,1290 0/0:33,0:33:81:0,81,1215 0/0:44,0:44:99:0,109,1647 0/0:30,0:30:63:0,63,945 0/0:30,0:30:66:0,66,973 0/0:33,0:33:63:0,63,945 0/0:49,0:49:99:0,120,1420 0/0:67,0:67:99:0,120,1800 0/0:54,0:54:99:0,117,1755 0/0:38,0:38:81:0,81,1305 0/0:54,0:54:99:0,117,1755 0/0:57,0:57:99:0,108,1620 0/0:54,0:54:99:0,120,1800 0/0:34,0:34:81:0,81,1215 0/0:34,0:34:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:38,0:38:96:0,96,1165 0/0:36,0:36:75:0,75,1125 0/0:34,0:34:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:28,0:28:66:0,66,925 0/0:39,0:39:68:0,68,1124 0/0:37,0:37:67:0,67,1219 0/0:28,0:28:69:0,69,860 0/0:32,0:32:72:0,72,1080 0/0:36,0:36:62:0,62,1241 0/0:43,0:43:99:0,105,1575 0/0:71,0:71:99:0,120,1800 0/0:32,0:32:61:0,61,1000 0/0:26,0:26:60:0,60,900 0/0:30,0:30:66:0,66,990 0/0:41,0:41:87:0,87,1305 0/0:42,0:42:93:0,93,1395 0/0:29,0:29:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:31,0:31:65:0,65,901 0/0:35,0:35:78:0,78,1253 0/0:58,0:58:99:0,117,1755 0/0:26,0:26:69:0,69,820 0/0:24,0:24:60:0,60,784 0/0:88,0:88:99:0,120,1800 0/0:30,0:30:75:0,75,1111 0/0:31,0:31:66:0,66,990 0/0:37,0:37:84:0,84,1260 0/0:29,0:29:67:0,67,940 0/0:34,0:34:66:0,66,990 0/0:55,0:55:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:34,0:34:78:0,78,1170 0/0:33,0:33:69:0,69,1035 0/0:45,0:45:99:0,99,1485 0/0:38,0:38:69:0,69,1080 0/0:32,0:32:65:0,65,990 0/0:31,0:31:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:38,0:38:69:0,69,1035 0/0:34,0:34:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:33,0:33:81:0,81,1088 0/0:38,0:38:87:0,87,1305 0/0:29,0:29:60:0,60,900 0/0:45,0:45:99:0,116,1646 0/1:56,63:119:99:1741,0,1687 0/0:40,0:40:87:0,87,1305 0/0:32,0:32:84:0,84,1260 0/0:75,0:75:68:0,68,1800 0/0:55,0:55:99:0,105,1575 0/0:45,0:45:96:0,96,1440 0/0:29,0:29:60:0,60,900 0/0:29,0:29:63:0,63,945 1/1:0,115:115:99:3864,345,0 0/1:53,50:103:99:1224,0,1675 0/0:26,0:26:66:0,66,942 0/0:45,0:45:99:0,102,1530 0/0:27,0:27:63:0,63,945 0/0:47,0:47:93:0,93,1395 +20 17597531 rs2236252 C T 299336.00 PASS HWP=0.0;AC=33;culprit=FS;MQ0=0;ReadPosRankSum=0.455;AN=200;InbreedingCoeff=0.1616;AF=0.217;GQ_STDDEV=297.0;FS=0.0;DP=38424;GQ_MEAN=247.09;POSITIVE_TRAIN_SITE;VQSLOD=6.87;ClippingRankSum=-0.284;BaseQRankSum=-2.98;MLEAF=0.217;MLEAC=378;MQ=59.74;QD=19.61;DB;MQRankSum=-0.071;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:26,27:53:99:807,0,814 0/0:49,0:49:99:0,120,1800 0/1:27,16:43:99:428,0,860 0/0:41,0:41:93:0,93,1395 0/0:47,0:47:99:0,106,1710 0/0:60,0:60:99:0,120,1800 0/1:22,21:43:99:622,0,671 0/0:40,0:40:87:0,87,1305 0/1:30,31:61:99:933,0,946 0/0:63,0:63:99:0,120,1800 0/0:51,0:51:90:0,90,1800 0/0:48,0:48:99:0,108,1620 0/1:31,36:67:99:1082,0,1090 0/1:27,26:53:99:778,0,793 0/0:23,0:23:60:0,60,721 0/1:13,21:34:99:625,0,396 0/0:17,0:17:39:0,39,585 0/1:18,18:36:99:546,0,569 0/0:24,0:24:63:0,63,945 0/0:38,0:38:90:0,90,1290 0/0:19,0:19:39:0,39,585 0/0:27,0:27:63:0,63,945 0/0:34,0:34:75:0,75,1290 0/0:33,0:33:81:0,81,1215 0/0:44,0:44:99:0,109,1647 0/0:29,0:29:66:0,66,990 0/0:32,0:32:59:0,59,1101 0/0:41,0:41:93:0,93,1395 0/0:49,0:49:99:0,120,1420 0/0:67,0:67:99:0,120,1800 0/1:29,26:55:99:692,0,870 0/0:38,0:38:81:0,81,1305 0/0:54,0:54:99:0,117,1755 0/0:57,0:57:99:0,108,1620 0/0:54,0:54:99:0,120,1800 0/0:34,0:34:81:0,81,1215 0/0:34,0:34:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:36,0:36:75:0,75,1125 0/0:29,0:29:66:0,66,990 0/0:28,0:28:70:0,70,773 0/0:24,0:24:60:0,60,900 0/0:39,0:39:68:0,68,1124 0/0:27,0:27:65:0,65,1035 0/0:31,0:31:73:0,73,1170 0/0:27,0:27:72:0,72,819 0/1:20,23:43:99:628,0,561 0/0:43,0:43:99:0,105,1575 0/0:71,0:71:99:0,120,1800 0/0:32,0:32:61:0,61,1000 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 1/1:0,40:40:99:1412,120,0 0/0:42,0:42:93:0,93,1395 0/0:26,0:26:54:0,54,810 0/0:23,0:23:60:0,60,900 0/0:31,0:31:65:0,65,901 0/1:21,18:39:99:471,0,621 0/0:58,0:58:99:0,117,1755 0/0:26,0:26:69:0,69,820 0/1:13,14:27:99:418,0,378 0/0:88,0:88:99:0,120,1800 0/1:13,22:35:99:683,0,366 0/0:23,0:23:63:0,63,945 0/0:37,0:37:84:0,84,1260 0/0:28,0:28:60:0,60,900 0/0:24,0:24:69:0,69,1035 0/0:55,0:55:99:0,120,1800 0/0:28,0:28:72:0,72,1080 0/0:34,0:34:78:0,78,1170 0/0:33,0:33:69:0,69,1035 0/0:45,0:45:99:0,99,1485 0/0:24,0:24:63:0,63,945 0/0:25,0:25:66:0,66,990 0/0:13,0:13:30:0,30,450 0/0:32,0:32:78:0,78,1170 0/1:14,12:26:99:359,0,480 0/0:27,0:27:63:0,63,945 0/0:32,0:32:67:0,67,1125 0/0:25,0:25:63:0,63,777 0/1:10,16:26:99:478,0,289 0/0:30,0:30:87:0,87,828 0/0:38,0:38:87:0,87,1305 0/1:15,13:28:99:375,0,446 1/1:0,45:45:99:1476,134,0 0/1:21,19:40:99:596,0,772 0/0:40,0:40:87:0,87,1305 0/0:32,0:32:84:0,84,1260 0/0:75,0:75:68:0,68,1800 1/1:0,54:54:99:1949,162,0 1/1:0,43:43:99:1554,129,0 0/1:8,14:22:99:439,0,240 0/1:14,10:24:99:274,0,433 0/0:35,0:35:81:0,81,1215 0/1:22,20:42:99:608,0,799 0/1:11,7:18:99:200,0,360 1/1:0,45:45:99:1523,134,0 0/1:12,9:21:99:268,0,324 0/1:17,24:41:99:702,0,524 +20 17599214 rs2328181 T C 2209320.00 PASS HWP=1.0;AC=200;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.197;AN=200;InbreedingCoeff=-0.0116;AF=0.989;GQ_STDDEV=161.34;FS=0.0;DP=64035;GQ_MEAN=235.99;POSITIVE_TRAIN_SITE;VQSLOD=3.45;ClippingRankSum=0.765;BaseQRankSum=1.19;MLEAF=0.989;MLEAC=1720;MQ=59.63;QD=34.61;DB;MQRankSum=0.953;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:0,65:65:99:2332,195,0 1/1:0,53:53:99:1838,159,0 1/1:0,41:41:99:1429,123,0 1/1:0,75:75:99:2617,225,0 1/1:0,59:59:99:2133,177,0 1/1:0,67:67:99:2267,201,0 1/1:0,66:66:99:2217,198,0 1/1:0,55:55:99:1881,165,0 1/1:0,68:68:99:2523,204,0 1/1:0,55:55:99:1974,165,0 1/1:0,62:62:99:2215,186,0 1/1:0,47:47:99:1676,141,0 1/1:0,73:73:99:2637,219,0 1/1:0,67:67:99:2273,201,0 1/1:0,23:23:69:799,69,0 1/1:1,37:38:83:1308,83,0 1/1:0,64:64:99:2304,192,0 1/1:0,47:47:99:1583,141,0 1/1:0,52:52:99:1735,156,0 1/1:0,50:50:99:1757,150,0 1/1:0,39:39:99:1334,117,0 1/1:0,55:55:99:1768,165,0 1/1:0,47:47:99:1678,141,0 1/1:0,166:166:99:5941,498,0 1/1:0,185:185:99:6248,555,0 1/1:0,48:48:99:1752,143,0 1/1:0,68:68:99:2360,204,0 1/1:0,55:55:99:2002,165,0 1/1:0,95:95:99:3564,286,0 1/1:0,104:104:99:3734,312,0 1/1:0,52:52:99:1816,156,0 1/1:0,99:99:99:3363,297,0 1/1:1,110:111:99:3880,321,0 1/1:0,110:110:99:4006,330,0 1/1:1,118:119:99:4230,331,0 1/1:0,89:89:99:2938,267,0 1/1:0,101:101:99:3368,303,0 1/1:0,44:44:99:1615,132,0 1/1:0,40:40:99:1317,118,0 1/1:0,60:60:99:2171,180,0 1/1:0,45:45:99:1645,135,0 1/1:1,49:50:99:1794,128,0 1/1:0,60:60:99:2170,180,0 1/1:0,56:56:99:1965,168,0 1/1:0,74:74:99:2590,221,0 1/1:0,73:73:99:2662,219,0 1/1:0,61:61:99:2240,183,0 1/1:0,65:65:99:2375,195,0 1/1:0,81:81:99:3118,244,0 1/1:0,79:79:99:3098,238,0 1/1:0,62:62:99:2217,185,0 1/1:0,64:64:99:2275,192,0 1/1:0,47:47:99:1651,141,0 1/1:0,51:51:99:1882,153,0 1/1:0,59:59:99:2217,177,0 1/1:0,52:52:99:1874,156,0 1/1:0,63:63:99:2268,189,0 1/1:0,87:87:99:2954,259,0 1/1:0,70:70:99:2497,210,0 1/1:0,58:58:99:2288,174,0 1/1:0,56:56:99:1995,168,0 1/1:0,62:62:99:2242,186,0 1/1:0,132:132:99:4850,397,0 1/1:0,63:63:99:2170,188,0 1/1:0,57:57:99:2031,171,0 1/1:0,42:42:99:1510,126,0 1/1:0,33:33:99:1275,99,0 1/1:0,53:53:99:2040,158,0 1/1:0,59:59:99:2322,177,0 1/1:0,45:45:99:1531,135,0 1/1:0,56:56:99:1925,168,0 1/1:0,60:60:99:2294,180,0 1/1:0,81:81:99:3007,244,0 1/1:0,61:61:99:2249,183,0 1/1:0,44:44:99:1572,132,0 1/1:0,42:42:99:1622,126,0 1/1:0,48:48:99:1737,144,0 1/1:0,49:49:99:1737,146,0 1/1:0,43:43:99:1654,129,0 1/1:0,66:66:99:2476,198,0 1/1:0,28:28:84:1025,84,0 1/1:0,37:37:99:1360,111,0 1/1:0,22:22:66:772,66,0 1/1:0,60:60:99:2214,180,0 1/1:0,54:54:99:2132,162,0 1/1:0,67:67:99:2533,201,0 1/1:0,108:108:99:3633,324,0 1/1:0,95:95:99:3314,285,0 1/1:1,51:52:99:1742,124,0 1/1:0,112:112:99:4070,335,0 1/1:0,142:142:99:4704,426,0 1/1:0,107:107:99:3535,321,0 1/1:0,63:63:99:2340,189,0 1/1:0,40:40:99:1532,120,0 1/1:0,95:95:99:3361,285,0 1/1:0,93:93:99:2896,279,0 1/1:0,41:41:99:1496,123,0 1/1:1,49:50:99:1819,140,0 1/1:0,34:34:99:1231,102,0 1/1:0,39:39:99:1454,117,0 +20 17599289 . G A 555.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=1.36;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=21.63;FS=4.946;DP=26731;GQ_MEAN=68.26;VQSLOD=2.6;ClippingRankSum=-0.431;BaseQRankSum=-1.47;MLEAF=5.747E-4;MLEAC=1;MQ=59.58;QD=10.29;MQRankSum=0.959;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:31,0:31:69:0,69,1035 0/0:25,0:25:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:32,0:32:75:0,75,1125 0/0:26,0:26:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:35,0:35:60:0,60,900 0/0:22,0:22:60:0,60,785 0/0:29,0:29:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:30,0:30:69:0,69,1035 0/0:26,0:26:72:0,72,1080 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:35,0:35:66:0,66,990 0/0:35,0:35:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:32,0:32:69:0,69,1035 0/0:32,0:32:69:0,69,1035 0/0:35,0:35:75:0,75,1125 0/0:27,0:27:63:0,63,945 0/0:38,0:38:87:0,87,1305 0/0:39,0:39:84:0,84,1260 0/0:39,0:39:84:0,84,1260 0/0:36,0:36:87:0,87,1305 0/0:36,0:36:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:30,0:30:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:28,0:28:66:0,66,990 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:31,0:31:75:0,75,1125 0/0:39,0:39:90:0,90,1395 0/0:31,0:31:72:0,72,1080 0/0:28,0:28:69:0,69,1035 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:32,0:32:69:0,69,1035 0/0:38,0:38:60:0,60,900 0/0:40,0:40:93:0,93,1395 0/0:28,0:28:69:0,69,1035 0/0:31,0:31:78:0,78,1170 0/0:24,0:24:60:0,60,900 0/1:32,22:54:99:606,0,988 0/0:28,0:28:66:0,66,990 0/0:38,0:38:96:0,96,1440 0/0:26,0:26:60:0,60,900 0/0:41,0:41:93:0,93,1395 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:30,0:30:69:0,69,1035 0/0:35,0:35:84:0,84,1260 0/0:29,0:29:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:32,0:32:69:0,69,1035 0/0:26,0:26:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:33,0:33:69:0,69,1035 0/0:30,0:30:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:23,0:23:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:24,0:24:61:0,61,874 0/0:31,0:31:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:38,0:38:66:0,66,990 0/0:23,0:23:60:0,60,893 0/0:34,0:34:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:36,0:36:87:0,87,1305 0/0:24,0:24:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:36,0:36:66:0,66,990 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:31,0:31:81:0,81,1215 0/0:21,0:21:60:0,60,900 0/0:31,0:31:60:0,60,900 +20 17600232 rs12230 G A 779.36 PASS HWP=1.0;AC=3;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.0;AN=198;InbreedingCoeff=-0.0091;AF=0.002877;GQ_STDDEV=17.23;FS=0.0;DP=11927;GQ_MEAN=35.3;POSITIVE_TRAIN_SITE;VQSLOD=5.7;ClippingRankSum=0.689;BaseQRankSum=1.38;MLEAF=0.002877;MLEAC=5;MQ=60.0;QD=15.91;DB;MQRankSum=0.529;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:20,0:20:60:0,60,706 0/0:9,0:9:24:0,24,347 0/0:15,0:15:39:0,39,539 0/0:10,0:10:27:0,27,405 0/0:19,0:19:48:0,48,720 0/0:28,0:28:78:0,78,1170 0/0:18,0:18:51:0,51,765 0/0:15,0:15:39:0,39,585 0/0:17,0:17:42:0,42,630 0/0:16,0:16:48:0,48,564 0/0:15,0:15:39:0,39,585 0/0:11,0:11:33:0,33,390 0/0:12,0:12:33:0,33,495 0/0:21,0:21:60:0,60,796 0/0:9,0:9:21:0,21,315 ./.:0,0:0:.:. 0/0:11,0:11:30:0,30,430 0/0:9,0:9:27:0,27,344 0/0:10,0:10:24:0,24,360 0/0:8,0:8:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:10,0:10:25:0,25,351 0/0:11,0:11:33:0,33,388 0/0:11,0:11:24:0,24,360 0/0:18,0:18:48:0,48,720 0/0:11,0:11:21:0,21,315 0/0:13,0:13:22:0,22,444 0/0:15,0:15:33:0,33,495 0/0:20,0:20:51:0,51,765 0/0:17,0:17:39:0,39,585 0/0:12,0:12:30:0,30,450 0/0:15,0:15:42:0,42,630 0/0:26,0:26:60:0,60,900 0/0:29,0:29:49:0,49,902 0/0:22,0:22:51:0,51,765 0/0:13,0:13:33:0,33,495 0/0:17,0:17:51:0,51,642 0/0:8,0:8:24:0,24,292 0/0:14,0:14:27:0,27,405 0/0:13,0:13:33:0,33,495 0/0:8,0:8:21:0,21,315 0/0:10,0:10:27:0,27,343 0/0:9,0:9:21:0,21,315 0/0:14,0:14:34:0,34,477 0/0:24,0:24:54:0,54,733 0/0:18,0:18:42:0,42,630 0/0:13,0:13:25:0,25,450 0/0:11,0:11:24:0,24,360 0/0:13,0:13:30:0,30,450 0/0:7,0:7:21:0,21,279 0/0:13,0:13:33:0,33,495 0/0:9,0:9:27:0,27,329 0/0:7,0:7:12:0,12,180 0/0:10,0:10:27:0,27,405 0/0:13,0:13:24:0,24,360 0/0:11,0:11:24:0,24,344 0/0:16,0:16:39:0,39,585 0/0:10,0:10:23:0,23,357 0/0:12,0:12:27:0,27,405 0/0:15,0:15:42:0,42,630 0/0:13,0:13:30:0,30,450 0/0:8,0:8:24:0,24,299 0/0:20,0:20:60:0,60,818 0/0:9,0:9:21:0,21,275 0/0:11,0:11:24:0,24,360 0/0:9,0:9:27:0,27,316 0/0:7,0:7:21:0,21,290 0/1:5,5:10:99:157,0,120 0/0:14,0:14:42:0,42,508 0/0:3,0:3:9:0,9,110 0/0:9,0:9:24:0,24,360 0/1:5,7:12:99:223,0,138 0/0:11,0:11:30:0,30,450 0/0:8,0:8:21:0,21,315 0/0:9,0:9:24:0,24,332 0/0:2,0:2:6:0,6,51 0/1:2,4:6:56:138,0,56 0/0:16,0:16:27:0,27,536 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:5,0:5:15:0,15,193 0/0:5,0:5:12:0,12,180 0/0:4,0:4:6:0,6,90 0/0:8,0:8:21:0,21,243 0/0:15,0:15:4:0,4,463 0/0:11,0:11:22:0,22,450 0/0:15,0:15:42:0,42,630 0/0:13,0:13:39:0,39,491 0/0:12,0:12:30:0,30,450 0/0:30,0:30:69:0,69,1112 0/0:18,0:18:48:0,48,720 0/0:16,0:16:36:0,36,540 0/0:9,0:9:8:0,8,278 0/0:4,0:4:12:0,12,140 0/0:22,0:22:63:0,63,881 0/0:10,0:10:30:0,30,382 0/0:9,0:9:24:0,24,314 0/0:15,0:15:36:0,36,520 0/0:7,0:7:21:0,21,281 0/0:8,0:8:21:0,21,315 +20 17600357 rs11960 G A 388302.00 PASS HWP=0.0;AC=121;culprit=FS;MQ0=0;ReadPosRankSum=0.339;AN=200;InbreedingCoeff=0.3219;AF=0.382;GQ_STDDEV=240.78;FS=0.593;DP=28414;GQ_MEAN=206.74;POSITIVE_TRAIN_SITE;VQSLOD=4.31;ClippingRankSum=-0.273;BaseQRankSum=-1.246;MLEAF=0.382;MLEAC=664;MQ=59.61;QD=20.46;DB;MQRankSum=0.217;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:23,18:41:99:559,0,628 1/1:0,31:31:93:1029,93,0 0/1:22,28:50:99:756,0,619 1/1:1,57:58:99:1874,171,0 0/0:23,0:23:60:0,60,900 0/1:38,22:60:99:534,0,1081 0/1:31,24:55:99:723,0,955 1/1:1,42:43:99:1341,126,0 0/1:32,23:55:99:597,0,998 1/1:2,64:66:99:2093,192,0 0/0:37,0:37:29:0,29,1177 0/1:26,19:45:99:504,0,729 0/0:21,0:21:60:0,60,900 0/1:24,25:49:99:670,0,683 0/0:12,0:12:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/1:10,22:32:99:639,0,221 1/1:0,33:33:99:1076,99,0 0/0:21,0:21:60:0,60,812 0/0:21,0:21:60:0,60,777 0/1:18,11:29:99:270,0,563 0/1:5,16:21:99:464,0,134 1/1:0,75:75:99:2582,225,0 1/1:0,69:69:99:2529,207,0 0/0:27,0:27:60:0,60,874 1/1:1,35:36:77:1273,77,0 1/1:0,30:30:90:1063,90,0 0/1:10,23:33:99:691,0,292 1/1:0,39:39:99:1273,117,0 0/1:17,16:33:99:415,0,498 0/0:20,0:20:60:0,60,768 0/1:28,15:43:99:417,0,951 1/1:0,60:60:99:2082,180,0 0/0:38,0:38:72:0,72,1080 0/0:22,0:22:63:0,63,828 0/0:27,0:27:63:0,63,945 1/1:0,23:23:69:823,69,0 1/1:0,31:31:93:1051,93,0 1/1:0,36:36:99:1292,108,0 1/1:0,20:20:60:742,60,0 1/1:0,24:24:72:855,72,0 1/1:0,25:25:75:819,75,0 0/1:16,16:32:99:488,0,479 1/1:0,22:22:66:739,66,0 1/1:0,39:39:99:1381,117,0 1/1:0,29:29:87:1038,87,0 1/1:0,25:25:75:879,75,0 1/1:0,41:41:99:1420,123,0 1/1:0,28:28:84:946,84,0 1/1:0,33:33:98:1121,98,0 0/1:15,16:31:99:474,0,470 0/1:15,10:25:99:276,0,481 0/1:14,13:27:99:380,0,438 1/1:0,37:37:99:1294,111,0 0/1:17,10:27:99:269,0,495 1/1:0,42:42:99:1545,126,0 1/1:0,33:33:99:1156,99,0 0/1:21,15:36:99:463,0,608 1/1:0,29:29:87:1092,87,0 1/1:0,17:17:51:627,51,0 0/0:28,0:28:66:0,66,990 1/1:0,62:62:99:2232,186,0 0/1:14,15:29:99:468,0,418 1/1:0,31:31:93:1092,93,0 1/1:0,26:26:78:920,78,0 0/1:7,10:17:99:269,0,221 0/1:9,8:17:99:237,0,329 0/1:27,19:46:99:560,0,804 1/1:0,13:13:39:436,39,0 1/1:0,33:33:99:1122,99,0 1/1:0,30:30:90:1052,90,0 1/1:0,36:36:99:1209,108,0 0/1:16,13:29:99:295,0,520 1/1:0,17:17:51:619,51,0 1/1:0,11:11:33:390,33,0 1/1:0,20:20:60:712,60,0 0/1:14,12:26:99:325,0,492 1/1:0,26:26:78:930,78,0 1/1:0,23:23:69:855,69,0 1/1:0,16:16:48:579,48,0 0/1:6,9:15:99:263,0,173 1/1:0,23:23:69:806,69,0 1/1:0,28:28:84:955,84,0 0/1:14,13:27:99:376,0,457 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,875 0/1:39,38:77:99:996,0,1113 0/1:23,10:33:99:268,0,734 1/1:0,61:61:99:2088,183,0 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:14,11:25:99:324,0,468 0/1:9,12:21:99:333,0,286 0/0:22,0:22:63:0,63,881 0/0:20,0:20:60:0,60,749 0/0:11,0:11:24:0,24,360 0/0:30,0:30:75:0,75,1125 0/0:25,0:25:60:0,60,869 0/0:28,0:28:60:0,60,885 +20 17600367 rs2229889 C T 1661.71 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.631;AN=200;InbreedingCoeff=-0.0023;AF=0.001724;GQ_STDDEV=35.15;FS=2.565;DP=21622;GQ_MEAN=59.13;POSITIVE_TRAIN_SITE;VQSLOD=4.9;ClippingRankSum=-1.753;BaseQRankSum=-1.418;MLEAF=0.001724;MLEAC=3;MQ=59.6;QD=12.22;DB;MQRankSum=0.433;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:27,0:27:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:29,0:29:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:42,0:42:72:0,72,1080 0/0:41,0:41:81:0,81,1215 0/0:27,0:27:66:0,66,990 0/0:34,0:34:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:26,0:26:62:0,62,990 0/0:31,0:31:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:27,0:27:75:0,75,1125 0/0:12,0:12:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:29,0:29:72:0,72,1080 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,812 0/0:21,0:21:60:0,60,777 0/0:26,0:26:66:0,66,990 0/0:14,0:14:24:0,24,360 0/0:47,0:47:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:27,0:27:60:0,60,874 0/0:31,0:31:72:0,72,1060 0/0:23,0:23:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:20,0:20:60:0,60,768 0/0:31,0:31:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:38,0:38:72:0,72,1080 0/0:22,0:22:63:0,63,828 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:28,0:28:69:0,69,1035 0/0:14,0:14:21:0,21,315 0/0:23,0:23:54:0,54,810 0/0:26,0:26:63:0,63,945 0/0:32,0:32:62:0,62,1125 0/0:19,0:19:48:0,48,720 0/0:30,0:30:66:0,66,990 0/0:26,0:26:49:0,49,890 0/0:24,0:24:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:30,0:30:78:0,78,976 0/0:26,0:26:66:0,66,990 0/0:15,0:15:27:0,27,405 0/0:15,0:15:21:0,21,315 0/0:31,0:31:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:34,0:34:63:0,63,945 0/0:26,0:26:62:0,62,952 0/0:29,0:29:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:28,0:28:66:0,66,990 0/0:44,0:44:60:0,60,900 0/0:27,0:27:63:0,63,977 0/0:9,0:9:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:13,0:13:30:0,30,450 0/0:33,0:33:66:0,66,990 0/0:8,0:8:21:0,21,315 0/0:25,0:25:60:0,60,900 0/0:29,0:29:61:0,61,968 0/0:29,0:29:66:0,66,990 0/0:24,0:24:66:0,66,990 0/0:15,0:15:36:0,36,540 0/0:9,0:9:21:0,21,315 0/0:13,0:13:27:0,27,405 0/0:23,0:23:66:0,66,958 0/0:22,0:22:60:0,60,900 0/0:13,0:13:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:13,0:13:27:0,27,405 0/0:13,0:13:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,875 0/0:39,0:39:69:0,69,1035 0/0:29,0:29:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:16,0:16:27:0,27,405 0/0:22,0:22:63:0,63,881 0/1:26,21:47:99:567,0,734 0/0:11,0:11:24:0,24,360 0/0:30,0:30:75:0,75,1125 0/0:16,0:16:21:0,21,315 0/0:28,0:28:60:0,60,885 +20 17600393 . C T 107.85 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.884;AN=200;InbreedingCoeff=-0.008;AF=5.754E-4;GQ_STDDEV=19.96;FS=2.363;DP=14271;GQ_MEAN=35.07;VQSLOD=1.42;ClippingRankSum=0.884;BaseQRankSum=0.53;MLEAF=5.754E-4;MLEAC=1;MQ=60.0;QD=7.19;MQRankSum=0.177;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:12,0:12:36:0,36,449 0/0:19,0:19:21:0,21,315 0/0:11,0:11:24:0,24,360 0/0:32,0:32:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:37,0:37:60:0,60,900 0/0:13,0:13:33:0,33,473 0/0:8,0:8:21:0,21,315 0/0:13,0:13:30:0,30,450 0/0:30,0:30:60:0,60,900 0/0:10,0:10:24:0,24,360 0/0:13,0:13:30:0,30,450 0/0:10,0:10:27:0,27,363 0/0:15,0:15:33:0,33,495 0/0:2,0:2:3:0,3,45 0/0:9,0:9:21:0,21,315 0/0:9,0:9:24:0,24,360 0/0:10,0:10:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:3,0:3:6:0,6,90 0/0:47,0:47:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:13,0:13:21:0,21,315 0/0:13,0:13:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:15,0:15:21:0,21,315 0/0:12,0:12:30:0,30,450 0/0:7,0:7:21:0,21,247 0/0:20,0:20:60:0,60,768 0/0:12,0:12:24:0,24,360 0/0:27,0:27:60:0,60,900 0/0:38,0:38:72:0,72,1080 0/0:9,0:9:21:0,21,315 0/0:27,0:27:63:0,63,945 0/0:18,0:18:24:0,24,360 0/0:19,0:19:42:0,42,630 0/0:23,0:23:27:0,27,405 0/0:5,0:5:12:0,12,147 0/0:16,0:16:21:0,21,315 0/0:15,0:15:27:0,27,405 0/0:12,0:12:25:0,25,400 0/0:12,0:12:24:0,24,360 0/0:13,0:13:21:0,21,315 0/0:17,0:17:24:0,24,360 0/0:10,0:10:21:0,21,315 0/0:16,0:16:36:0,36,585 0/0:10,0:10:24:0,24,360 0/0:13,0:13:21:0,21,315 0/0:14,0:14:24:0,24,360 0/0:4,0:4:9:0,9,135 0/0:15,0:15:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:11,0:11:22:0,22,360 0/0:16,0:16:36:0,36,540 0/0:17,0:17:30:0,30,450 0/0:15,0:15:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:15,0:15:25:0,25,495 0/0:15,0:15:33:0,33,495 0/0:12,0:12:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:17,0:17:11:0,11,522 0/0:9,0:9:21:0,21,315 0/0:6,0:6:6:0,6,90 0/0:33,0:33:66:0,66,990 0/0:7,0:7:12:0,12,180 0/0:11,0:11:21:0,21,315 0/0:17,0:17:27:0,27,405 0/0:19,0:19:36:0,36,540 0/0:14,0:14:21:0,21,315 0/0:4,0:4:6:0,6,90 0/0:4,0:4:9:0,9,135 0/0:5,0:5:6:0,6,90 0/0:10,0:10:21:0,21,315 0/0:9,0:9:6:0,6,90 0/0:4,0:4:6:0,6,90 0/0:14,0:14:21:0,21,315 0/0:4,0:4:12:0,12,152 0/0:2,0:2:6:0,6,77 0/0:11,0:11:24:0,24,360 0/0:10,0:10:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,875 0/0:39,0:39:69:0,69,1035 0/0:14,0:14:30:0,30,450 0/0:31,0:31:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:12,0:12:30:0,30,450 0/0:4,0:4:9:0,9,135 0/0:10,0:10:21:0,21,315 0/0:30,0:30:60:0,60,900 0/0:11,0:11:24:0,24,360 0/0:12,0:12:24:0,24,360 0/1:9,6:15:99:158,0,263 0/0:15,0:15:24:0,24,360 +20 17601458 rs190319933 G C 95.79 PASS HWP=1.0;AC=1;culprit=QD;MQ0=0;ReadPosRankSum=0.244;AN=200;InbreedingCoeff=-0.0046;AF=5.754E-4;GQ_STDDEV=20.12;FS=0.0;DP=14981;GQ_MEAN=42.43;VQSLOD=3.11;ClippingRankSum=-1.0;BaseQRankSum=-1.977;MLEAF=5.754E-4;MLEAC=1;MQ=60.0;QD=7.98;DB;MQRankSum=0.244;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:8,0:8:21:0,21,276 0/0:9,0:9:24:0,24,360 0/0:11,0:11:24:0,24,360 0/0:21,0:21:63:0,63,716 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:13,0:13:21:0,21,315 0/0:14,0:14:24:0,24,360 0/0:26,0:26:62:0,62,945 0/0:16,0:16:36:0,36,540 0/0:20,0:20:60:0,60,782 0/0:23,0:23:63:0,63,807 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:8,0:8:24:0,24,279 0/0:8,0:8:21:0,21,306 0/0:5,0:5:12:0,12,180 0/0:13,0:13:30:0,30,450 0/0:13,0:13:33:0,33,480 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:26,0:26:66:0,66,990 0/0:22,0:22:60:0,60,900 0/0:15,0:15:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:14,0:14:24:0,24,360 0/0:20,0:20:60:0,60,809 0/0:4,0:4:6:0,6,90 0/0:8,0:8:18:0,18,270 0/0:8,0:8:21:0,21,315 0/0:8,0:8:24:0,24,312 0/0:8,0:8:21:0,21,315 0/0:8,0:8:21:0,21,273 0/0:6,0:6:15:0,15,225 0/0:15,0:15:24:0,24,360 0/0:10,0:10:24:0,24,360 0/0:9,0:9:21:0,21,324 0/0:8,0:8:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,778 0/0:22,0:22:60:0,60,741 0/0:12,0:12:30:0,30,450 0/0:15,0:15:39:0,39,585 0/0:10,0:10:21:0,21,315 0/0:13,0:13:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:14,0:14:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:11,0:11:21:0,21,323 0/0:23,0:23:60:0,60,790 0/0:11,0:11:21:0,21,315 0/0:8,0:8:21:0,21,266 0/0:24,0:24:60:0,60,900 0/0:16,0:16:39:0,39,585 0/0:11,0:11:23:0,23,394 0/0:8,0:8:21:0,21,315 0/0:5,0:5:9:0,9,135 0/0:2,0:2:6:0,6,62 0/0:29,0:29:61:0,61,1080 0/0:8,0:8:21:0,21,304 0/0:12,0:12:33:0,33,495 0/1:7,5:12:99:146,0,222 0/0:10,0:10:21:0,21,315 0/0:8,0:8:24:0,24,302 0/0:8,0:8:21:0,21,315 0/0:11,0:11:24:0,24,360 0/0:11,0:11:21:0,21,315 0/0:2,0:2:6:0,6,62 0/0:7,0:7:21:0,21,207 0/0:11,0:11:21:0,21,315 0/0:8,0:8:21:0,21,247 0/0:4,0:4:6:0,6,90 0/0:2,0:2:6:0,6,67 0/0:7,0:7:21:0,21,221 0/0:7,0:7:21:0,21,203 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:5,0:5:6:0,6,90 0/0:20,0:20:60:0,60,705 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:4,0:4:6:0,6,90 0/0:29,0:29:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:5,0:5:9:0,9,135 0/0:8,0:8:21:0,21,241 0/0:12,0:12:24:0,24,360 +20 17602109 . C T 1309.32 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.732;AN=200;InbreedingCoeff=-0.0015;AF=0.001149;GQ_STDDEV=25.99;FS=0.876;DP=18965;GQ_MEAN=58.34;VQSLOD=3.24;ClippingRankSum=0.626;BaseQRankSum=2.01;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=15.59;MQRankSum=0.344;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,833 0/0:24,0:24:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:21,0:21:60:0,60,814 0/0:23,0:23:60:0,60,806 0/0:20,0:20:60:0,60,787 0/0:22,0:22:63:0,63,821 0/0:12,0:12:33:0,33,495 0/0:14,0:14:33:0,33,572 0/0:24,0:24:60:0,60,900 0/0:13,0:13:36:0,36,540 0/0:10,0:10:27:0,27,333 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,718 0/0:7,0:7:21:0,21,249 0/0:20,0:20:60:0,60,720 0/1:10,12:22:99:366,0,249 0/0:20,0:20:60:0,60,717 0/0:20,0:20:60:0,60,649 0/0:21,0:21:60:0,60,710 0/0:22,0:22:66:0,66,818 0/0:34,0:34:87:0,87,1305 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,837 0/0:21,0:21:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:25,0:25:60:0,60,835 0/0:23,0:23:60:0,60,866 0/1:25,37:62:99:1020,0,691 0/0:26,0:26:72:0,72,1046 0/0:25,0:25:69:0,69,1035 0/0:28,0:28:72:0,72,1080 0/0:21,0:21:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,869 0/0:23,0:23:60:0,60,765 0/0:26,0:26:75:0,75,911 0/0:21,0:21:60:0,60,900 0/0:8,0:8:21:0,21,282 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,763 0/0:24,0:24:60:0,60,891 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,863 0/0:22,0:22:60:0,60,845 0/0:21,0:21:63:0,63,821 0/0:20,0:20:60:0,60,782 0/0:10,0:10:30:0,30,386 0/0:16,0:16:36:0,36,540 0/0:22,0:22:63:0,63,855 0/0:25,0:25:60:0,60,900 0/0:21,0:21:63:0,63,773 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,731 0/0:22,0:22:60:0,60,778 0/0:25,0:25:66:0,66,990 0/0:20,0:20:60:0,60,733 0/0:24,0:24:60:0,60,900 0/0:7,0:7:21:0,21,256 0/0:7,0:7:21:0,21,260 0/0:21,0:21:57:0,57,855 0/0:20,0:20:60:0,60,811 0/0:7,0:7:21:0,21,263 0/0:22,0:22:60:0,60,900 0/0:15,0:15:35:0,35,530 0/0:24,0:24:66:0,66,990 0/0:20,0:20:60:0,60,722 0/0:20,0:20:60:0,60,716 0/0:7,0:7:21:0,21,259 0/0:22,0:22:60:0,60,900 0/0:24,0:24:33:0,33,804 0/0:8,0:8:24:0,24,281 0/0:21,0:21:60:0,60,726 0/0:7,0:7:21:0,21,275 0/0:8,0:8:24:0,24,299 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:63:0,63,790 0/0:20,0:20:60:0,60,714 0/0:22,0:22:60:0,60,835 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,741 0/0:24,0:24:62:0,62,885 0/0:22,0:22:60:0,60,864 0/0:22,0:22:60:0,60,900 0/0:8,0:8:23:0,23,259 0/0:10,0:10:30:0,30,359 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,702 0/0:9,0:9:24:0,24,307 0/0:21,0:21:60:0,60,760 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,712 +20 17602196 rs73898358 A G 46967.50 PASS HWP=0.1993;AC=5;culprit=MQ;MQ0=0;ReadPosRankSum=0.427;AN=200;InbreedingCoeff=0.0467;AF=0.068;GQ_STDDEV=121.25;FS=0.0;DP=16222;GQ_MEAN=77.57;POSITIVE_TRAIN_SITE;VQSLOD=6.48;ClippingRankSum=0.217;BaseQRankSum=1.35;MLEAF=0.068;MLEAC=119;MQ=60.0;QD=16.12;DB;MQRankSum=0.212;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:17,0:17:39:0,39,585 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:15,0:15:6:0,6,517 0/0:18,0:18:42:0,42,675 0/0:15,0:15:36:0,36,540 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,895 0/0:12,0:12:30:0,30,450 0/0:14,0:14:33:0,33,572 0/0:17,0:17:45:0,45,675 0/0:22,0:22:60:0,60,887 0/0:10,0:10:27:0,27,333 0/0:14,0:14:36:0,36,540 0/0:12,0:12:27:0,27,405 0/0:9,0:9:24:0,24,360 0/0:23,0:23:60:0,60,900 0/1:9,12:21:99:356,0,281 0/0:12,0:12:21:0,21,315 0/1:10,9:19:99:288,0,335 0/0:19,0:19:48:0,48,720 0/0:22,0:22:66:0,66,818 0/0:34,0:34:87:0,87,1305 0/0:23,0:23:63:0,63,945 0/0:22,0:22:47:0,47,765 0/0:23,0:23:51:0,51,765 0/0:23,0:23:60:0,60,843 0/0:25,0:25:60:0,60,835 0/0:15,0:15:20:0,20,540 0/1:12,17:29:99:605,0,399 0/1:20,11:31:99:324,0,694 0/0:25,0:25:69:0,69,1035 0/0:28,0:28:72:0,72,1080 0/0:10,0:10:21:0,21,315 0/0:26,0:26:63:0,63,945 0/0:10,0:10:21:0,21,315 0/0:16,0:16:39:0,39,585 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:8,0:8:21:0,21,282 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:15,0:15:36:0,36,540 0/0:24,0:24:60:0,60,891 0/0:25,0:25:63:0,63,945 0/0:18,0:18:40:0,40,675 0/0:14,0:14:30:0,30,450 0/0:25,0:25:63:0,63,945 0/0:20,0:20:60:0,60,782 0/0:9,0:9:24:0,24,336 0/0:11,0:11:24:0,24,360 0/0:30,0:30:57:0,57,855 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,842 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:54:0,54,810 0/0:16,0:16:18:0,18,552 0/0:22,0:22:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:15,0:15:36:0,36,540 0/0:24,0:24:60:0,60,900 0/0:7,0:7:21:0,21,256 0/0:4,0:4:6:0,6,90 0/1:9,3:12:87:87,0,320 0/0:20,0:20:60:0,60,811 0/0:7,0:7:21:0,21,228 0/0:12,0:12:24:0,24,360 0/0:21,0:21:60:0,60,843 0/0:24,0:24:66:0,66,990 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:6,0:6:15:0,15,207 0/0:11,0:11:30:0,30,409 0/0:13,0:13:30:0,30,450 0/0:9,0:9:21:0,21,315 0/0:12,0:12:24:0,24,360 0/0:15,0:15:34:0,34,540 0/0:8,0:8:21:0,21,292 0/0:22,0:22:60:0,60,900 0/0:13,0:13:33:0,33,495 0/0:15,0:15:35:0,35,585 0/0:10,0:10:21:0,21,315 0/0:17,0:17:39:0,39,585 0/0:25,0:25:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:24,0:24:62:0,62,885 0/0:22,0:22:60:0,60,864 0/0:24,0:24:48:0,48,720 0/0:13,0:13:27:0,27,481 0/0:8,0:8:21:0,21,312 0/0:21,0:21:60:0,60,900 0/0:12,0:12:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:11,0:11:24:0,24,360 0/0:9,0:9:21:0,21,315 0/0:13,0:13:27:0,27,405 +20 17602446 rs145138078 C T 2622.31 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.864;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=59.26;FS=0.687;DP=22453;GQ_MEAN=67.83;VQSLOD=3.48;ClippingRankSum=-0.385;BaseQRankSum=1.03;MLEAF=0.001149;MLEAC=2;MQ=59.39;QD=16.39;DB;MQRankSum=0.299;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:63:0,63,914 0/0:27,0:27:69:0,69,928 0/0:25,0:25:60:0,60,900 0/0:23,0:23:66:0,66,983 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:23,0:23:63:0,63,861 0/0:23,0:23:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:21,0:21:60:0,60,722 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,758 0/0:23,0:23:60:0,60,817 0/0:25,0:25:60:0,60,900 0/0:32,0:32:81:0,81,1092 0/0:24,0:24:66:0,66,744 0/1:20,31:51:99:991,0,578 0/0:28,0:28:60:0,60,900 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,864 0/0:25,0:25:66:0,66,986 0/0:25,0:25:69:0,69,1035 0/0:29,0:29:78:0,78,987 0/0:42,0:42:99:0,99,1485 0/0:32,0:32:78:0,78,1170 0/0:23,0:23:60:0,60,900 0/1:54,55:109:99:1708,0,1712 0/0:23,0:23:60:0,60,900 0/0:39,0:39:99:0,111,1405 0/0:22,0:22:60:0,60,880 0/0:21,0:21:60:0,60,879 0/0:23,0:23:60:0,60,900 0/0:28,0:28:68:0,68,970 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:34,0:34:84:0,84,1260 0/0:25,0:25:75:0,75,945 0/0:20,0:20:60:0,60,724 0/0:22,0:22:60:0,60,721 0/0:39,0:39:99:0,105,1575 0/0:22,0:22:63:0,63,945 0/0:28,0:28:75:0,75,1015 0/0:26,0:26:69:0,69,1035 0/0:21,0:21:63:0,63,749 0/0:21,0:21:60:0,60,716 0/0:28,0:28:72:0,72,1125 0/0:22,0:22:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,895 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,740 0/0:31,0:31:87:0,87,1305 0/0:26,0:26:66:0,66,1044 0/0:26,0:26:74:0,74,913 0/0:21,0:21:60:0,60,804 0/0:26,0:26:67:0,67,993 0/0:21,0:21:60:0,60,851 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,703 0/0:37,0:37:93:0,93,1383 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:69:0,69,824 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,719 0/0:23,0:23:60:0,60,900 0/0:23,0:23:61:0,61,945 0/0:20,0:20:60:0,60,780 0/0:8,0:8:24:0,24,311 0/0:20,0:20:60:0,60,715 0/0:26,0:26:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,716 0/0:22,0:22:60:0,60,849 0/0:20,0:20:60:0,60,720 0/0:21,0:21:60:0,60,714 0/0:33,0:33:96:0,96,1440 0/0:23,0:23:63:0,63,782 0/0:29,0:29:60:0,60,900 0/0:27,0:27:72:0,72,1029 0/0:24,0:24:60:0,60,860 0/0:23,0:23:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:25,0:25:63:0,63,990 +20 17602571 rs2229886 A G 30853.90 PASS HWP=1.0;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.1;AN=200;InbreedingCoeff=-0.0146;AF=0.014;GQ_STDDEV=213.77;FS=0.64;DP=24082;GQ_MEAN=97.63;POSITIVE_TRAIN_SITE;VQSLOD=4.59;ClippingRankSum=0.161;BaseQRankSum=0.532;MLEAF=0.014;MLEAC=25;MQ=59.75;QD=13.5;DB;MQRankSum=0.419;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:63:0,63,914 0/0:27,0:27:69:0,69,928 0/0:25,0:25:60:0,60,900 0/0:23,0:23:66:0,66,983 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:23,0:23:63:0,63,861 0/0:23,0:23:63:0,63,945 0/0:26,0:26:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:22,0:22:63:0,63,794 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,758 0/0:23,0:23:60:0,60,817 0/0:25,0:25:60:0,60,900 0/0:32,0:32:81:0,81,1092 0/0:24,0:24:66:0,66,744 0/0:25,0:25:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:21,0:21:60:0,60,779 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,864 0/0:25,0:25:66:0,66,986 0/0:25,0:25:69:0,69,1035 0/0:29,0:29:78:0,78,987 0/0:42,0:42:99:0,99,1485 0/0:32,0:32:78:0,78,1170 0/0:23,0:23:60:0,60,900 0/0:61,0:61:99:0,120,1800 0/0:23,0:23:60:0,60,900 0/0:39,0:39:99:0,111,1405 0/0:22,0:22:60:0,60,880 0/0:21,0:21:60:0,60,879 0/0:23,0:23:60:0,60,900 0/0:28,0:28:68:0,68,970 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/1:47,27:74:99:733,0,1480 0/0:25,0:25:75:0,75,945 0/0:20,0:20:60:0,60,724 0/0:22,0:22:60:0,60,721 0/0:39,0:39:99:0,105,1575 0/0:22,0:22:63:0,63,945 0/0:28,0:28:75:0,75,1015 0/1:51,40:91:99:1249,0,1563 0/0:21,0:21:63:0,63,749 0/0:21,0:21:60:0,60,716 0/0:28,0:28:72:0,72,1125 0/0:22,0:22:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,895 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,740 0/0:31,0:31:87:0,87,1305 0/0:26,0:26:66:0,66,1044 0/0:26,0:26:74:0,74,913 0/0:21,0:21:60:0,60,804 0/0:26,0:26:67:0,67,993 0/0:21,0:21:60:0,60,851 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:37,0:37:93:0,93,1383 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:24,0:24:69:0,69,824 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,719 0/0:23,0:23:60:0,60,900 0/0:23,0:23:61:0,61,945 0/0:20,0:20:60:0,60,780 0/0:25,0:25:63:0,63,945 0/0:20,0:20:60:0,60,715 0/0:26,0:26:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,716 0/0:22,0:22:60:0,60,849 0/0:20,0:20:60:0,60,720 0/0:21,0:21:60:0,60,714 0/0:33,0:33:96:0,96,1440 0/0:23,0:23:63:0,63,782 0/0:29,0:29:60:0,60,900 0/0:27,0:27:72:0,72,1029 0/0:24,0:24:60:0,60,860 0/0:23,0:23:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:25,0:25:66:0,66,990 0/0:25,0:25:63:0,63,990 +20 17605240 rs6034867 A T 376024.00 PASS HWP=1.0;AC=194;culprit=MQ;MQ0=0;ReadPosRankSum=-0.134;AN=194;InbreedingCoeff=-0.0032;AF=1.0;GQ_STDDEV=21.6;FS=0.0;DP=11747;GQ_MEAN=40.36;POSITIVE_TRAIN_SITE;VQSLOD=5.05;ClippingRankSum=0.0;BaseQRankSum=1.49;MLEAF=1.0;MLEAC=1730;MQ=60.0;QD=32.23;DB;MQRankSum=0.267;CCC=1730;NCC=5 GT:AD:DP:GQ:PL 1/1:0,9:9:27:290,27,0 1/1:0,5:5:15:149,15,0 1/1:0,4:4:12:94,12,0 1/1:0,8:8:24:281,24,0 1/1:0,7:7:21:257,21,0 1/1:0,11:11:33:359,33,0 1/1:0,8:8:24:249,24,0 1/1:0,19:19:57:690,57,0 1/1:0,7:7:21:213,21,0 1/1:0,5:5:15:194,15,0 1/1:0,11:11:33:334,33,0 1/1:0,7:7:21:244,21,0 1/1:0,8:8:24:243,24,0 1/1:0,3:3:9:113,9,0 ./.:0,0:0:.:. ./.:2,0:2:.:. 1/1:0,3:3:9:85,9,0 1/1:0,9:9:27:297,27,0 1/1:0,3:3:9:114,9,0 1/1:0,6:6:18:199,18,0 1/1:0,4:4:12:150,12,0 1/1:0,5:5:15:163,15,0 1/1:0,3:3:9:88,9,0 1/1:0,32:32:96:1194,96,0 1/1:0,31:31:92:937,92,0 1/1:0,10:10:30:315,30,0 1/1:0,10:10:30:319,30,0 1/1:0,10:10:30:333,30,0 1/1:0,14:14:42:460,42,0 1/1:0,25:25:74:773,74,0 1/1:0,12:12:36:368,36,0 1/1:0,16:16:48:530,48,0 1/1:0,14:14:42:437,42,0 1/1:0,17:17:51:514,51,0 1/1:0,16:16:48:525,48,0 1/1:0,9:9:27:264,27,0 1/1:0,16:16:48:500,48,0 1/1:0,5:5:15:176,15,0 1/1:0,10:10:30:357,30,0 1/1:0,16:16:48:517,48,0 1/1:0,6:6:18:221,18,0 1/1:0,15:15:45:527,45,0 1/1:0,11:11:33:382,33,0 1/1:0,7:7:21:230,21,0 1/1:0,16:16:47:519,47,0 1/1:0,11:11:33:342,33,0 1/1:0,11:11:33:374,33,0 1/1:0,12:12:36:413,36,0 1/1:0,12:12:36:364,36,0 1/1:0,11:11:33:373,33,0 1/1:0,20:20:60:631,60,0 1/1:0,11:11:33:404,33,0 1/1:0,10:10:30:342,30,0 1/1:0,6:6:18:202,18,0 1/1:0,6:6:18:207,18,0 1/1:0,12:12:36:386,36,0 1/1:0,21:21:63:714,63,0 1/1:0,16:16:48:528,48,0 1/1:0,7:7:21:207,21,0 1/1:0,9:9:27:333,27,0 1/1:0,18:18:54:605,54,0 1/1:0,5:5:15:158,15,0 1/1:0,23:23:69:751,69,0 1/1:0,11:11:33:391,33,0 1/1:0,6:6:18:195,18,0 1/1:0,3:3:9:114,9,0 1/1:0,7:7:21:244,21,0 1/1:0,6:6:18:214,18,0 1/1:0,10:10:30:362,30,0 1/1:0,6:6:18:215,18,0 1/1:0,8:8:24:277,24,0 1/1:0,9:9:27:300,27,0 1/1:0,10:10:30:351,30,0 1/1:0,9:9:27:295,27,0 1/1:0,9:9:27:291,27,0 1/1:0,6:6:18:186,18,0 1/1:0,6:6:18:172,18,0 1/1:0,4:4:12:141,12,0 1/1:0,9:9:27:282,27,0 1/1:0,13:13:39:432,39,0 1/1:0,6:6:18:197,18,0 1/1:0,11:11:33:371,33,0 1/1:0,4:4:12:122,12,0 1/1:0,10:10:30:360,30,0 1/1:0,8:8:24:236,24,0 1/1:0,16:16:48:540,48,0 1/1:0,11:11:33:358,33,0 1/1:0,22:22:66:730,66,0 ./.:1,0:1:.:. 1/1:0,15:15:45:475,45,0 1/1:0,19:19:57:601,57,0 1/1:0,11:11:33:368,33,0 1/1:0,3:3:9:89,9,0 1/1:0,8:8:24:244,24,0 1/1:0,15:15:45:434,45,0 1/1:0,11:11:33:369,33,0 1/1:0,4:4:12:132,12,0 1/1:0,14:14:42:464,42,0 1/1:0,10:10:30:317,30,0 1/1:0,8:8:24:268,24,0 +20 17605269 rs61742496 C T 15645.20 PASS HWP=0.0574;AC=3;culprit=MQ;MQ0=0;ReadPosRankSum=0.312;AN=194;InbreedingCoeff=0.0165;AF=0.053;GQ_STDDEV=50.16;FS=0.0;DP=8658;GQ_MEAN=33.54;POSITIVE_TRAIN_SITE;VQSLOD=6.13;ClippingRankSum=0.289;BaseQRankSum=0.731;MLEAF=0.055;MLEAC=95;MQ=60.0;QD=12.75;DB;MQRankSum=0.231;CCC=1730;NCC=5 GT:AD:DP:GQ:PL 0/0:2,0:2:6:0,6,79 0/0:2,0:2:6:0,6,76 0/0:4,0:4:9:0,9,125 0/0:6,0:6:6:0,6,90 0/0:2,0:2:6:0,6,76 0/0:8,0:8:21:0,21,290 0/0:7,0:7:21:0,21,244 0/0:9,0:9:21:0,21,298 0/0:8,0:8:21:0,21,257 0/0:3,0:3:6:0,6,90 0/0:8,0:8:21:0,21,309 0/0:8,0:8:21:0,21,291 0/0:8,0:8:21:0,21,253 0/0:4,0:4:9:0,9,135 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 0/0:2,0:2:6:0,6,72 0/0:9,0:9:21:0,21,315 0/0:2,0:2:6:0,6,70 0/0:7,0:7:21:0,21,246 0/0:7,0:7:21:0,21,198 0/1:1,4:5:21:113,0,21 ./.:0,0:0:.:. 0/0:20,0:20:45:0,45,675 0/0:23,0:23:51:0,51,765 0/0:8,0:8:18:0,18,270 0/0:8,0:8:21:0,21,266 0/0:8,0:8:18:0,18,270 0/0:9,0:9:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/1:6,7:13:99:199,0,171 0/0:11,0:11:21:0,21,315 0/0:9,0:9:21:0,21,327 0/0:3,0:3:6:0,6,89 0/0:8,0:8:21:0,21,315 0/0:4,0:4:12:0,12,142 0/0:7,0:7:12:0,12,180 0/0:9,0:9:21:0,21,294 0/0:2,0:2:3:0,3,45 0/0:9,0:9:21:0,21,315 0/0:8,0:8:21:0,21,272 0/0:5,0:5:9:0,9,135 0/0:9,0:9:21:0,21,308 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:8,0:8:15:0,15,225 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,250 0/0:4,0:4:12:0,12,148 0/0:6,0:6:15:0,15,212 0/0:10,0:10:21:0,21,315 0/0:11,0:11:25:0,25,405 0/0:11,0:11:24:0,24,360 0/0:3,0:3:6:0,6,90 0/0:9,0:9:21:0,21,304 0/1:12,5:17:99:101,0,356 0/0:4,0:4:6:0,6,90 0/0:10,0:10:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:7,0:7:21:0,21,226 0/0:3,0:3:9:0,9,88 0/0:3,0:3:6:0,6,90 ./.:7,0:7:.:. 0/0:10,0:10:27:0,27,396 0/0:5,0:5:9:0,9,135 0/0:6,0:6:12:0,12,180 0/0:7,0:7:21:0,21,272 0/0:7,0:7:21:0,21,218 0/0:8,0:8:21:0,21,278 0/0:8,0:8:12:0,12,180 0/0:7,0:7:21:0,21,217 0/0:7,0:7:21:0,21,219 0/0:6,0:6:15:0,15,225 0/0:5,0:5:9:0,9,135 0/0:5,0:5:12:0,12,180 0/0:4,0:4:9:0,9,135 0/0:3,0:3:6:0,6,90 0/0:2,0:2:6:0,6,62 0/0:7,0:7:21:0,21,217 0/0:7,0:7:15:0,15,225 0/0:6,0:6:12:0,12,180 0/0:8,0:8:21:0,21,279 0/0:8,0:8:21:0,21,238 0/0:2,0:2:6:0,6,72 0/0:9,0:9:22:0,22,290 0/0:12,0:12:21:0,21,315 0/0:8,0:8:18:0,18,270 0/0:2,0:2:0:0,0,45 0/0:2,0:2:6:0,6,74 0/0:9,0:9:21:0,21,315 0/0:11,0:11:27:0,27,334 0/0:8,0:8:21:0,21,256 0/0:2,0:2:6:0,6,87 0/0:3,0:3:6:0,6,126 0/0:7,0:7:21:0,21,270 +20 17606124 . C T 1911.31 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.92;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=51.76;FS=4.376;DP=32652;GQ_MEAN=86.54;VQSLOD=2.64;ClippingRankSum=1.2;BaseQRankSum=0.851;MLEAF=0.001149;MLEAC=2;MQ=60.0;QD=16.06;MQRankSum=0.148;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:81:0,81,1215 0/0:27,0:27:75:0,75,1125 0/0:48,0:48:99:0,105,1754 0/0:35,0:35:96:0,96,1331 0/0:23,0:23:69:0,69,869 0/0:43,0:43:85:0,85,1620 0/0:40,0:40:78:0,78,1170 0/0:35,0:35:99:0,99,1319 0/0:38,0:38:81:0,81,1485 0/0:50,0:50:99:0,120,1800 0/0:41,0:41:99:0,114,1710 0/0:32,0:32:87:0,87,1187 0/0:39,0:39:99:0,105,1575 0/0:44,0:44:99:0,108,1620 0/0:13,0:13:39:0,39,471 0/0:32,0:32:65:0,65,1129 0/0:26,0:26:75:0,75,1125 0/0:24,0:24:60:0,60,900 0/0:30,0:30:81:0,81,1157 0/1:22,23:45:99:697,0,651 0/0:26,0:26:60:0,60,900 0/0:23,0:23:69:0,69,829 0/0:28,0:28:69:0,69,1035 0/0:43,0:43:99:0,114,1710 0/0:67,0:67:99:0,120,1800 0/0:26,0:26:63:0,63,945 0/0:42,0:42:96:0,96,1440 0/0:46,0:46:99:0,108,1620 0/0:45,0:45:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/0:42,0:42:99:0,99,1485 0/1:36,38:74:99:1291,0,1301 0/0:65,0:65:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:27,0:27:69:0,69,1035 0/0:40,0:40:96:0,96,1440 0/0:28,0:28:69:0,69,1149 0/0:23,0:23:63:0,63,898 0/0:35,0:35:90:0,90,1350 0/0:29,0:29:63:0,63,945 0/0:31,0:31:65:0,65,1080 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:37,0:37:84:0,84,1260 0/0:46,0:46:99:0,104,1693 0/0:29,0:29:63:0,63,945 0/0:35,0:35:74:0,74,1094 0/0:40,0:40:99:0,111,1665 0/0:40,0:40:99:0,117,1416 0/0:37,0:37:78:0,78,1189 0/0:27,0:27:63:0,63,945 0/0:28,0:28:65:0,65,990 0/0:21,0:21:60:0,60,900 0/0:33,0:33:64:0,64,1035 0/0:23,0:23:60:0,60,900 0/0:34,0:34:93:0,93,1395 0/0:52,0:52:99:0,114,1710 0/0:32,0:32:77:0,77,1180 0/0:43,0:43:99:0,102,1530 0/0:30,0:30:69:0,69,1035 0/0:30,0:30:72:0,72,1080 0/0:68,0:68:99:0,120,1800 0/0:35,0:35:87:0,87,1305 0/0:31,0:31:81:0,81,1215 0/0:26,0:26:72:0,72,1080 0/0:23,0:23:63:0,63,857 0/0:24,0:24:60:0,60,900 0/0:44,0:44:99:0,120,1800 0/0:21,0:21:60:0,60,900 0/0:34,0:34:96:0,96,1221 0/0:27,0:27:69:0,69,1035 0/0:36,0:36:99:0,102,1530 0/0:21,0:21:63:0,63,868 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:72:0,72,910 0/0:25,0:25:69:0,69,1035 0/0:23,0:23:60:0,60,807 0/0:29,0:29:66:0,66,990 0/0:21,0:21:63:0,63,818 0/0:12,0:12:30:0,30,450 0/0:24,0:24:66:0,66,854 0/0:31,0:31:69:0,69,1035 0/0:27,0:27:62:0,62,945 0/0:23,0:23:63:0,63,945 0/0:41,0:41:99:0,120,1800 0/0:34,0:34:69:0,69,1035 0/0:26,0:26:78:0,78,956 0/0:54,0:54:99:0,120,1800 0/0:31,0:31:63:0,63,945 0/0:26,0:26:75:0,75,998 0/0:28,0:28:72:0,72,1125 0/0:20,0:20:60:0,60,730 0/0:32,0:32:72:0,72,1080 0/0:25,0:25:69:0,69,997 0/0:22,0:22:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,883 0/0:39,0:39:96:0,96,1440 +20 17606125 rs3828010 C T 20960.20 PASS HWP=0.0196;AC=5;culprit=MQ;MQ0=0;ReadPosRankSum=0.108;AN=200;InbreedingCoeff=0.1546;AF=0.014;GQ_STDDEV=106.04;FS=2.146;DP=32957;GQ_MEAN=98.99;POSITIVE_TRAIN_SITE;VQSLOD=3.27;ClippingRankSum=0.059;BaseQRankSum=-1.363;MLEAF=0.014;MLEAC=24;MQ=60.0;QD=18.29;DB;MQRankSum=-0.285;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:81:0,81,1215 0/0:27,0:27:75:0,75,1125 0/0:48,0:48:99:0,105,1754 0/0:35,0:35:96:0,96,1331 0/0:23,0:23:69:0,69,869 0/0:43,0:43:85:0,85,1620 0/0:40,0:40:78:0,78,1170 0/0:35,0:35:99:0,99,1319 0/0:38,0:38:81:0,81,1485 0/0:50,0:50:99:0,120,1800 0/0:41,0:41:99:0,114,1710 0/0:32,0:32:87:0,87,1187 0/1:28,27:55:99:910,0,828 0/0:44,0:44:99:0,108,1620 0/0:13,0:13:39:0,39,471 0/1:19,14:33:99:417,0,525 0/0:31,0:31:53:0,53,1074 0/0:24,0:24:60:0,60,900 0/0:30,0:30:81:0,81,1157 0/0:41,0:41:90:0,90,1350 0/0:26,0:26:60:0,60,900 0/0:23,0:23:69:0,69,829 0/0:28,0:28:69:0,69,1035 0/0:43,0:43:99:0,114,1710 0/0:67,0:67:99:0,120,1800 0/0:26,0:26:63:0,63,945 0/0:42,0:42:96:0,96,1440 0/0:46,0:46:99:0,108,1620 0/0:45,0:45:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/0:42,0:42:99:0,99,1485 0/0:45,0:45:99:0,105,1575 0/0:65,0:65:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:27,0:27:69:0,69,1035 0/0:40,0:40:96:0,96,1440 0/0:28,0:28:69:0,69,1149 0/0:23,0:23:63:0,63,898 0/0:35,0:35:90:0,90,1350 0/0:29,0:29:63:0,63,945 0/0:31,0:31:65:0,65,1080 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:37,0:37:84:0,84,1260 0/0:46,0:46:99:0,104,1693 0/0:29,0:29:63:0,63,945 0/0:35,0:35:74:0,74,1094 0/0:40,0:40:99:0,111,1665 0/0:40,0:40:99:0,117,1416 0/0:37,0:37:78:0,78,1189 0/0:27,0:27:63:0,63,945 0/0:28,0:28:65:0,65,990 0/0:21,0:21:60:0,60,900 0/0:33,0:33:64:0,64,1035 0/0:23,0:23:60:0,60,900 0/0:34,0:34:93:0,93,1395 0/0:52,0:52:99:0,114,1710 0/0:32,0:32:77:0,77,1180 0/0:43,0:43:99:0,102,1530 0/0:30,0:30:69:0,69,1035 0/0:30,0:30:72:0,72,1080 0/0:68,0:68:99:0,120,1800 0/0:35,0:35:87:0,87,1305 0/0:31,0:31:81:0,81,1215 0/0:26,0:26:72:0,72,1080 0/0:23,0:23:63:0,63,857 0/0:24,0:24:60:0,60,900 0/0:44,0:44:99:0,120,1800 0/0:21,0:21:60:0,60,900 0/0:34,0:34:96:0,96,1221 0/0:27,0:27:69:0,69,1035 0/0:36,0:36:99:0,102,1530 0/0:21,0:21:63:0,63,868 0/0:21,0:21:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:72:0,72,910 0/0:25,0:25:69:0,69,1035 0/0:23,0:23:60:0,60,807 0/0:29,0:29:66:0,66,990 0/0:21,0:21:63:0,63,818 0/0:12,0:12:30:0,30,450 0/0:24,0:24:66:0,66,854 0/0:31,0:31:69:0,69,1035 0/0:27,0:27:62:0,62,945 0/0:23,0:23:63:0,63,945 1/1:0,58:58:99:2265,175,0 0/0:34,0:34:69:0,69,1035 0/0:26,0:26:78:0,78,956 0/0:54,0:54:99:0,120,1800 0/0:31,0:31:63:0,63,945 0/0:26,0:26:75:0,75,998 0/0:28,0:28:72:0,72,1125 0/0:20,0:20:60:0,60,730 0/0:32,0:32:72:0,72,1080 0/1:16,28:44:99:932,0,485 0/0:22,0:22:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,883 0/0:39,0:39:96:0,96,1440 +20 17608161 rs148741935 G C 468.70 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.429;AN=200;InbreedingCoeff=-8.0E-4;AF=5.747E-4;GQ_STDDEV=24.66;FS=0.0;DP=24997;GQ_MEAN=65.67;POSITIVE_TRAIN_SITE;VQSLOD=5.18;ClippingRankSum=-0.133;BaseQRankSum=0.251;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=12.33;DB;MQRankSum=0.488;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:32,0:32:67:0,67,1209 0/0:30,0:30:72:0,72,1080 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:46,0:46:99:0,120,1800 0/0:28,0:28:63:0,63,945 0/0:19,0:19:51:0,51,765 0/0:29,0:29:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:27,0:27:81:0,81,1028 0/0:22,0:22:60:0,60,900 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:31,0:31:63:0,63,945 0/0:47,0:47:99:0,101,1575 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,696 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,895 0/0:27,0:27:60:0,60,900 0/0:21,0:21:39:0,39,765 0/0:21,0:21:60:0,60,900 0/0:21,0:21:29:0,29,694 0/0:22,0:22:60:0,60,808 0/0:25,0:25:66:0,66,884 0/0:28,0:28:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:65:0,65,900 0/0:21,0:21:48:0,48,720 0/0:17,0:17:11:0,11,594 0/0:29,0:29:60:0,60,900 0/0:21,0:21:60:0,60,757 0/0:25,0:25:54:0,54,810 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:26,0:26:60:0,60,900 0/0:19,0:19:48:0,48,720 0/0:22,0:22:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,831 0/0:27,0:27:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:17,0:17:31:0,31,576 0/0:30,0:30:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:17,0:17:40:0,40,667 0/0:21,0:21:39:0,39,585 0/0:23,0:23:63:0,63,945 0/0:24,0:24:61:0,61,922 0/0:23,0:23:63:0,63,945 0/0:27,0:27:62:0,62,1035 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,807 0/0:26,0:26:60:0,60,900 0/0:20,0:20:26:0,26,630 0/1:22,16:38:99:519,0,726 0/0:29,0:29:78:0,78,1170 0/0:27,0:27:63:0,63,945 0/0:36,0:36:99:0,105,1575 0/0:41,0:41:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:22,0:22:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:34,0:34:63:0,63,945 0/0:31,0:31:84:0,84,1260 0/0:20,0:20:60:0,60,792 0/0:26,0:26:60:0,60,900 0/0:23,0:23:31:0,31,851 0/0:27,0:27:69:0,69,1035 +20 17608170 rs2229888 C T 89122.10 PASS HWP=9.0E-4;AC=4;culprit=FS;MQ0=0;ReadPosRankSum=0.731;AN=200;InbreedingCoeff=0.1337;AF=0.079;GQ_STDDEV=219.24;FS=5.803;DP=27431;GQ_MEAN=130.84;POSITIVE_TRAIN_SITE;VQSLOD=2.7;ClippingRankSum=-0.105;BaseQRankSum=-0.882;MLEAF=0.079;MLEAC=138;MQ=59.48;QD=13.3;DB;MQRankSum=0.346;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:32,0:32:67:0,67,1209 0/0:30,0:30:72:0,72,1080 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:46,0:46:99:0,120,1800 0/0:28,0:28:63:0,63,945 0/0:19,0:19:51:0,51,765 0/0:29,0:29:75:0,75,1125 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/1:17,31:48:99:804,0,416 0/0:22,0:22:60:0,60,900 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:31,0:31:63:0,63,945 0/1:28,24:52:99:665,0,889 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,696 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,895 0/0:27,0:27:60:0,60,900 0/0:21,0:21:39:0,39,765 0/0:21,0:21:60:0,60,900 0/0:24,0:24:57:0,57,855 0/0:29,0:29:52:0,52,962 0/0:25,0:25:66:0,66,884 0/0:28,0:28:63:0,63,945 0/0:23,0:23:63:0,63,819 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:65:0,65,900 0/0:21,0:21:48:0,48,720 0/0:18,0:18:51:0,51,765 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:26,0:26:60:0,60,900 0/1:13,11:24:99:327,0,430 0/0:22,0:22:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,831 0/1:16,8:24:99:209,0,569 0/0:24,0:24:60:0,60,900 0/0:17,0:17:31:0,31,576 0/0:30,0:30:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,693 0/0:21,0:21:39:0,39,585 0/0:23,0:23:63:0,63,945 0/0:24,0:24:61:0,61,922 0/0:23,0:23:63:0,63,945 0/0:27,0:27:62:0,62,1035 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,807 0/0:26,0:26:60:0,60,900 0/0:20,0:20:26:0,26,630 0/0:25,0:25:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:27,0:27:63:0,63,945 0/0:36,0:36:99:0,105,1575 0/0:41,0:41:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:29,0:29:47:0,47,810 0/0:26,0:26:60:0,60,900 0/0:34,0:34:63:0,63,945 0/0:31,0:31:84:0,84,1260 0/0:20,0:20:60:0,60,792 0/0:26,0:26:60:0,60,900 0/0:22,0:22:51:0,51,765 0/0:27,0:27:69:0,69,1035 +20 17608233 rs1051954 C T 20117.20 PASS HWP=0.0196;AC=5;culprit=FS;MQ0=0;ReadPosRankSum=0.385;AN=200;InbreedingCoeff=0.1541;AF=0.014;GQ_STDDEV=109.73;FS=0.0;DP=25047;GQ_MEAN=78.47;POSITIVE_TRAIN_SITE;VQSLOD=6.91;ClippingRankSum=-0.546;BaseQRankSum=1.65;MLEAF=0.014;MLEAC=24;MQ=59.75;QD=15.78;DB;MQRankSum=-0.028;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:32,0:32:67:0,67,1209 0/0:30,0:30:72:0,72,1080 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:66:0,66,990 0/1:40,36:76:99:1020,0,1098 0/0:28,0:28:63:0,63,945 0/0:20,0:20:60:0,60,760 0/1:17,18:35:99:470,0,493 0/0:23,0:23:60:0,60,900 0/0:31,0:31:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/0:29,0:29:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:31,0:31:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,696 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,895 0/0:27,0:27:60:0,60,900 0/0:26,0:26:65:0,65,990 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:29,0:29:62:0,62,990 0/0:25,0:25:66:0,66,884 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,884 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:65:0,65,900 0/0:22,0:22:60:0,60,900 0/0:17,0:17:39:0,39,585 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:27,0:27:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,831 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:30,0:30:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:17,0:17:42:0,42,630 0/0:23,0:23:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:24,0:24:61:0,61,922 0/0:23,0:23:63:0,63,945 0/0:27,0:27:62:0,62,1035 0/0:22,0:22:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:24,0:24:60:0,60,900 0/0:19,0:19:51:0,51,765 0/0:25,0:25:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:27,0:27:63:0,63,945 1/1:0,52:52:99:1900,156,0 0/0:41,0:41:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:34,0:34:63:0,63,945 0/1:24,29:53:99:830,0,571 0/0:20,0:20:60:0,60,792 0/0:26,0:26:60:0,60,900 0/0:18,0:18:44:0,44,675 0/0:27,0:27:69:0,69,1035 +20 17608245 . C A 1514.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=-0.915;AN=200;InbreedingCoeff=-0.0018;AF=0.001724;GQ_STDDEV=17.7;FS=1.992;DP=24223;GQ_MEAN=63.36;VQSLOD=1.76;ClippingRankSum=0.993;BaseQRankSum=-2.032;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=19.42;MQRankSum=-0.564;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:32,0:32:67:0,67,1209 0/0:30,0:30:72:0,72,1080 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:20,0:20:60:0,60,760 0/0:25,0:25:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:24,0:24:51:0,51,765 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/0:19,0:19:42:0,42,630 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:31,0:31:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,696 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:63:0,63,895 0/0:27,0:27:60:0,60,900 0/0:18,0:18:36:0,36,540 0/0:19,0:19:45:0,45,675 0/0:22,0:22:60:0,60,900 0/0:29,0:29:62:0,62,990 0/0:25,0:25:66:0,66,884 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,884 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:65:0,65,900 0/0:22,0:22:60:0,60,900 0/0:17,0:17:39:0,39,585 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:20,0:20:45:0,45,675 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,831 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:30,0:30:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:17,0:17:42:0,42,630 0/0:25,0:25:63:0,63,945 0/0:27,0:27:55:0,55,1023 0/0:24,0:24:61:0,61,922 0/0:23,0:23:63:0,63,945 0/0:27,0:27:62:0,62,1035 0/0:22,0:22:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:26,0:26:75:0,75,967 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:27,0:27:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:41,0:41:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:34,0:34:63:0,63,945 0/0:30,0:30:72:0,72,1125 0/0:17,0:17:45:0,45,619 0/1:9,17:26:99:509,0,287 0/0:18,0:18:44:0,44,675 0/0:27,0:27:69:0,69,1035 +20 17608288 . C T 578.69 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.146;AN=200;InbreedingCoeff=-7.0E-4;AF=5.747E-4;GQ_STDDEV=15.51;FS=3.145;DP=24145;GQ_MEAN=63.04;VQSLOD=3.05;ClippingRankSum=-0.665;BaseQRankSum=1.83;MLEAF=5.747E-4;MLEAC=1;MQ=60.0;QD=16.07;MQRankSum=-0.406;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:32,0:32:67:0,67,1209 0/0:30,0:30:72:0,72,1080 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:20,0:20:60:0,60,760 0/0:26,0:26:65:0,65,1080 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:60:0,60,900 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/0:26,0:26:65:0,65,959 0/0:27,0:27:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:33,0:33:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:33,0:33:66:0,66,990 0/0:31,0:31:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,696 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:20,0:20:51:0,51,765 0/0:23,0:23:62:0,62,823 0/0:24,0:24:60:0,60,900 0/0:29,0:29:62:0,62,990 0/0:25,0:25:66:0,66,884 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,799 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:65:0,65,900 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/1:14,22:36:99:629,0,323 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:26,0:26:60:0,60,900 0/0:18,0:18:48:0,48,720 0/0:22,0:22:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:16,0:16:21:0,21,585 0/0:16,0:16:25:0,25,518 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:24,0:24:40:0,40,855 0/0:26,0:26:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,737 0/0:29,0:29:78:0,78,1170 0/0:16,0:16:39:0,39,585 0/0:24,0:24:61:0,61,922 0/0:23,0:23:63:0,63,945 0/0:27,0:27:62:0,62,1035 0/0:22,0:22:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:24,0:24:45:0,45,790 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:78:0,78,1170 0/0:27,0:27:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:41,0:41:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:34,0:34:63:0,63,945 0/0:30,0:30:72:0,72,1125 0/0:23,0:23:60:0,60,783 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,797 0/0:25,0:25:60:0,60,900 +20 17608348 rs138823930 CGAG C 34541.50 PASS HWP=0.5683;AC=7;culprit=MQRankSum;MQ0=0;ReadPosRankSum=0.111;AN=200;InbreedingCoeff=0.0272;AF=0.047;GQ_STDDEV=116.15;FS=2.215;DP=23070;GQ_MEAN=90.26;POSITIVE_TRAIN_SITE;VQSLOD=3.14;ClippingRankSum=-0.159;BaseQRankSum=3.19;MLEAF=0.047;MLEAC=81;MQ=57.39;QD=14.24;DB;MQRankSum=-0.652;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:31,0:31:69:0,69,1035 0/0:33,0:33:66:0,66,990 0/0:27,0:27:60:0,60,900 0/0:27,0:27:43:0,43,936 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:11,0:11:30:0,30,450 0/0:16,0:16:39:0,39,585 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:18,0:18:36:0,36,540 0/0:22,0:22:60:0,60,900 0/1:17,10:27:99:370,0,942 0/0:26,0:26:60:0,60,900 0/1:17,9:26:99:328,0,926 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/1:9,10:19:99:394,0,460 0/0:27,0:27:66:0,66,990 0/0:25,0:25:60:0,60,900 0/1:17,15:32:99:572,0,870 0/0:25,0:25:60:0,60,900 0/0:29,0:29:57:0,57,855 0/0:31,0:31:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,696 0/0:15,0:15:36:0,36,540 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:12,0:12:24:0,24,360 0/0:12,0:12:30:0,30,450 0/0:25,0:25:63:0,63,945 0/0:29,0:29:62:0,62,990 0/0:24,0:24:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:22,0:22:57:0,57,855 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:65:0,65,900 0/0:17,0:17:42:0,42,630 0/0:22,0:22:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:11,7:18:99:262,0,536 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:12,0:12:30:0,30,450 0/0:29,0:29:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:21,0:21:60:0,60,760 0/0:25,0:25:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:31,0:31:63:0,63,945 0/0:35,0:35:27:0,27,405 0/0:21,0:21:60:0,60,900 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:12,0:12:27:0,27,405 0/0:10,0:10:21:0,21,315 0/0:34,0:34:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:25,0:25:63:0,63,945 0/1:4,3:7:99:115,0,191 0/1:3,6:9:99:239,0,153 +20 17608356 . T TA 1906.95 PASS HWP=1.0;AC=1;culprit=FS;MQ0=0;ReadPosRankSum=-0.372;AN=200;InbreedingCoeff=-0.0033;AF=0.002874;GQ_STDDEV=27.24;FS=9.423;DP=21086;GQ_MEAN=56.28;POSITIVE_TRAIN_SITE;VQSLOD=2.4;ClippingRankSum=0.382;BaseQRankSum=-0.382;MLEAF=0.002874;MLEAC=5;MQ=60.0;QD=16.16;MQRankSum=0.35;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:23,0:23:60:0,60,900 0/0:15,0:15:27:0,27,405 0/0:31,0:31:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:14,0:14:30:0,30,450 0/0:33,0:33:66:0,66,990 0/0:27,0:27:60:0,60,900 0/0:14,0:14:27:0,27,405 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:13,0:13:33:0,33,495 0/0:28,0:28:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:11,0:11:30:0,30,450 0/0:16,0:16:39:0,39,585 0/0:23,0:23:60:0,60,900 0/0:15,0:15:30:0,30,450 0/0:18,0:18:36:0,36,540 0/0:17,0:17:39:0,39,585 0/0:23,0:23:63:0,63,945 0/0:14,0:14:36:0,36,540 0/0:24,0:24:63:0,63,945 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/0:13,0:13:27:0,27,405 0/0:18,0:18:21:0,21,585 0/0:25,0:25:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:60:0,60,696 0/0:15,0:15:36:0,36,540 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:12,0:12:24:0,24,360 0/0:12,0:12:30:0,30,450 0/0:14,0:14:33:0,33,495 0/0:29,0:29:62:0,62,990 0/0:19,0:19:45:0,45,675 0/0:28,0:28:63:0,63,945 0/0:17,0:17:39:0,39,585 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:23,0:23:65:0,65,900 0/0:17,0:17:42:0,42,630 0/0:22,0:22:60:0,60,900 0/0:13,0:13:24:0,24,360 0/0:25,0:25:60:0,60,900 0/0:15,0:15:39:0,39,531 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:26,0:26:60:0,60,900 0/0:24,0:24:55:0,55,774 0/0:22,0:22:60:0,60,900 0/0:37,0:37:96:0,96,1440 0/0:23,0:23:60:0,60,900 0/0:23,0:23:51:0,51,758 0/0:24,0:24:60:0,60,900 0/0:12,0:12:21:0,21,315 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:24,0:24:60:0,60,900 0/0:14,0:14:33:0,33,495 0/0:26,0:26:60:0,60,900 0/0:12,0:12:30:0,30,450 0/0:22,0:22:57:0,57,855 0/0:12,0:12:27:0,27,405 0/0:15,0:15:36:0,36,540 0/0:24,0:24:60:0,60,900 0/0:16,0:16:39:0,39,585 0/0:22,0:22:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:14,0:14:33:0,33,495 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:31,0:31:63:0,63,945 0/1:12,19:31:99:570,0,330 0/0:21,0:21:60:0,60,900 0/0:34,0:34:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:29,0:29:60:0,60,900 0/0:12,0:12:27:0,27,405 0/0:10,0:10:21:0,21,315 0/0:17,0:17:21:0,21,315 0/0:16,0:16:39:0,39,585 0/0:9,0:9:21:0,21,315 0/0:18,0:18:42:0,42,630 0/0:5,0:5:12:0,12,180 0/0:7,0:7:15:0,15,225 +20 17608371 rs144629635 C T 685.73 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=-0.232;AN=200;InbreedingCoeff=-0.0027;AF=0.001724;GQ_STDDEV=22.86;FS=1.281;DP=18295;GQ_MEAN=47.35;POSITIVE_TRAIN_SITE;VQSLOD=3.95;ClippingRankSum=-0.29;BaseQRankSum=-1.826;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=12.7;DB;MQRankSum=0.047;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:13,0:13:33:0,33,495 0/0:15,0:15:27:0,27,405 0/0:19,0:19:42:0,42,630 0/0:19,0:19:36:0,36,540 0/0:14,0:14:30:0,30,450 0/0:20,0:20:51:0,51,765 0/0:18,0:18:45:0,45,675 0/0:14,0:14:27:0,27,405 0/0:31,0:31:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:20,0:20:42:0,42,630 0/0:13,0:13:33:0,33,495 0/0:28,0:28:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:11,0:11:30:0,30,450 0/0:16,0:16:39:0,39,585 0/0:20,0:20:48:0,48,720 0/0:15,0:15:30:0,30,450 0/0:12,0:12:30:0,30,422 0/0:17,0:17:39:0,39,585 0/0:18,0:18:33:0,33,495 0/0:14,0:14:36:0,36,540 0/0:21,0:21:57:0,57,855 0/0:41,0:41:97:0,97,1610 0/0:37,0:37:84:0,84,1260 0/0:13,0:13:27:0,27,405 0/0:18,0:18:21:0,21,585 0/0:25,0:25:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:16,0:16:36:0,36,540 0/0:20,0:20:48:0,48,720 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:75:0,75,1125 0/0:34,0:34:75:0,75,1125 0/0:20,0:20:39:0,39,585 0/0:15,0:15:36:0,36,540 0/0:14,0:14:33:0,33,495 0/0:24,0:24:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:12,0:12:24:0,24,360 0/0:12,0:12:30:0,30,450 0/0:14,0:14:33:0,33,495 0/0:29,0:29:62:0,62,990 0/0:17,0:17:33:0,33,495 0/0:28,0:28:63:0,63,945 0/1:12,6:18:99:142,0,383 0/0:24,0:24:54:0,54,810 0/0:18,0:18:42:0,42,630 0/0:18,0:18:39:0,39,585 0/0:23,0:23:65:0,65,900 0/0:17,0:17:42:0,42,630 0/0:16,0:16:30:0,30,450 0/0:13,0:13:24:0,24,360 0/0:19,0:19:42:0,42,630 0/0:15,0:15:39:0,39,531 0/0:25,0:25:63:0,63,945 0/0:35,0:35:69:0,69,1035 0/0:26,0:26:66:0,66,863 0/0:20,0:20:39:0,39,585 0/0:21,0:21:39:0,39,585 0/0:20,0:20:49:0,49,765 0/0:37,0:37:96:0,96,1440 0/0:23,0:23:60:0,60,900 0/0:23,0:23:54:0,54,810 0/0:16,0:16:45:0,45,675 0/0:12,0:12:21:0,21,315 0/0:15,0:15:36:0,36,600 0/0:22,0:22:31:0,31,675 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:14,0:14:33:0,33,495 0/0:26,0:26:60:0,60,900 0/0:12,0:12:30:0,30,450 0/0:16,0:16:33:0,33,495 0/0:12,0:12:27:0,27,405 0/0:15,0:15:36:0,36,540 0/0:14,0:14:30:0,30,450 0/0:16,0:16:39:0,39,585 0/0:15,0:15:36:0,36,540 0/0:5,0:5:12:0,12,180 0/0:9,0:9:18:0,18,270 0/0:14,0:14:33:0,33,495 0/0:18,0:18:42:0,42,630 0/0:24,0:24:60:0,60,900 0/0:13,0:13:27:0,27,405 0/0:19,0:19:30:0,30,450 0/0:18,0:18:39:0,39,585 0/0:18,0:18:39:0,39,585 0/0:34,0:34:87:0,87,1305 0/0:19,0:19:39:0,39,585 0/0:21,0:21:42:0,42,630 0/0:12,0:12:27:0,27,405 0/0:10,0:10:21:0,21,315 0/0:17,0:17:21:0,21,315 0/0:16,0:16:39:0,39,585 0/0:9,0:9:21:0,21,315 0/0:18,0:18:42:0,42,630 0/0:5,0:5:12:0,12,180 0/0:6,0:6:18:0,18,207 +20 17610512 rs45479602 C T 1260.73 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.115;AN=200;InbreedingCoeff=-0.001;AF=0.001724;GQ_STDDEV=34.89;FS=0.0;DP=24851;GQ_MEAN=65.66;VQSLOD=1.62;ClippingRankSum=-0.42;BaseQRankSum=0.556;MLEAF=0.001724;MLEAC=3;MQ=57.61;QD=12.24;DB;MQRankSum=0.397;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:28,0:28:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:75:0,75,1125 0/0:35,0:35:87:0,87,1305 0/0:42,0:42:99:0,111,1665 0/0:32,0:32:63:0,63,945 0/0:29,0:29:75:0,75,1046 0/0:36,0:36:77:0,77,1350 0/0:26,0:26:60:0,60,900 0/0:32,0:32:70:0,70,1080 0/0:34,0:34:78:0,78,1170 0/0:36,0:36:74:0,74,1151 0/0:28,0:28:63:0,63,945 0/0:16,0:16:36:0,36,518 0/0:25,0:25:63:0,63,945 0/0:34,0:34:68:0,68,1170 0/0:31,0:31:72:0,72,1080 0/0:10,0:10:20:0,20,353 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:9,0:9:20:0,20,354 0/0:17,0:17:30:0,30,450 0/0:20,0:20:42:0,42,630 0/0:27,0:27:66:0,66,990 0/0:49,0:49:99:0,111,1665 0/0:36,0:36:65:0,65,1142 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:34,0:34:75:0,75,1170 0/0:26,0:26:74:0,74,971 0/0:27,0:27:63:0,63,945 0/0:64,0:64:99:0,120,1800 0/0:25,0:25:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:17,0:17:33:0,33,585 0/0:12,0:12:27:0,27,405 0/0:13,0:13:22:0,22,405 0/0:18,0:18:24:0,24,360 0/0:27,0:27:60:0,60,900 0/0:26,0:26:66:0,66,969 0/0:24,0:24:69:0,69,873 0/0:30,0:30:69:0,69,1035 0/0:11,0:11:24:0,24,360 0/0:22,0:22:60:0,60,864 0/0:22,0:22:60:0,60,798 0/0:12,0:12:27:0,27,405 0/0:13,0:13:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:11,0:11:24:0,24,360 0/0:28,0:28:66:0,66,951 0/0:8,0:8:21:0,21,315 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,691 0/0:10,0:10:21:0,21,315 0/0:26,0:26:60:0,60,842 0/0:16,0:16:33:0,33,495 0/0:22,0:22:57:0,57,855 0/0:25,0:25:72:0,72,1080 0/0:14,0:14:27:0,27,405 0/0:15,0:15:26:0,26,450 0/0:25,0:25:60:0,60,900 0/1:2,14:16:24:441,0,24 0/0:10,0:10:24:0,24,360 0/0:29,0:29:69:0,69,1035 0/0:11,0:11:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:16,0:16:33:0,33,495 0/0:27,0:27:69:0,69,1024 0/0:11,0:11:24:0,24,360 0/0:20,0:20:60:0,60,757 0/0:9,0:9:24:0,24,360 0/0:21,0:21:24:0,24,360 0/0:21,0:21:60:0,60,779 0/0:10,0:10:21:0,21,315 0/1:20,8:28:99:175,0,598 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,286 0/0:15,0:15:33:0,33,495 0/0:23,0:23:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:22,0:22:60:0,60,787 0/0:42,0:42:88:0,88,1480 0/0:32,0:32:72:0,72,1080 0/0:25,0:25:63:0,63,945 0/0:32,0:32:65:0,65,1150 0/0:38,0:38:90:0,90,1350 0/0:30,0:30:63:0,63,945 0/0:18,0:18:13:0,13,597 0/0:23,0:23:60:0,60,900 0/0:38,0:38:93:0,93,1395 0/0:25,0:25:60:0,60,900 0/0:11,0:11:24:0,24,360 0/0:11,0:11:24:0,24,360 0/0:11,0:11:30:0,30,450 0/0:22,0:22:60:0,60,694 +20 17610535 rs11551701 C T 71337.00 PASS HWP=0.9042;AC=13;culprit=MQ;MQ0=0;ReadPosRankSum=0.365;AN=200;InbreedingCoeff=0.0053;AF=0.079;GQ_STDDEV=150.07;FS=0.0;DP=24067;GQ_MEAN=112.96;POSITIVE_TRAIN_SITE;VQSLOD=5.21;ClippingRankSum=-0.274;BaseQRankSum=0.81;MLEAF=0.079;MLEAC=137;MQ=60.0;QD=15.26;DB;MQRankSum=0.11;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:28,0:28:63:0,63,945 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:75:0,75,1125 0/0:35,0:35:87:0,87,1305 0/0:42,0:42:99:0,111,1665 0/0:32,0:32:63:0,63,945 0/0:29,0:29:75:0,75,1046 0/0:36,0:36:77:0,77,1350 0/0:26,0:26:60:0,60,900 0/0:32,0:32:70:0,70,1080 0/0:34,0:34:78:0,78,1170 0/0:36,0:36:74:0,74,1151 0/0:28,0:28:63:0,63,945 1/1:0,18:18:54:638,54,0 0/0:25,0:25:63:0,63,945 0/1:18,17:35:99:516,0,524 0/0:26,0:26:60:0,60,900 0/0:10,0:10:20:0,20,353 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:16,0:16:42:0,42,590 0/0:23,0:23:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:9,0:9:20:0,20,354 0/0:3,0:3:9:0,9,103 0/0:24,0:24:57:0,57,855 0/0:27,0:27:66:0,66,990 0/0:49,0:49:99:0,111,1665 0/0:36,0:36:65:0,65,1142 0/0:29,0:29:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:34,0:34:75:0,75,1170 0/0:32,0:32:68:0,68,1050 0/1:11,15:26:99:403,0,284 1/1:0,62:62:99:2286,186,0 0/0:21,0:21:60:0,60,731 0/0:24,0:24:60:0,60,900 0/0:17,0:17:33:0,33,585 0/0:12,0:12:27:0,27,405 0/0:12,0:12:27:0,27,405 0/0:10,0:10:8:0,8,266 0/0:14,0:14:20:0,20,450 0/1:7,12:19:99:391,0,180 0/0:24,0:24:60:0,60,877 0/0:11,0:11:21:0,21,360 0/0:11,0:11:24:0,24,360 0/0:23,0:23:51:0,51,765 0/0:22,0:22:60:0,60,798 0/0:15,0:15:45:0,45,553 0/0:7,0:7:21:0,21,240 0/0:7,0:7:21:0,21,254 0/0:11,0:11:24:0,24,360 0/0:17,0:17:39:0,39,585 0/0:7,0:7:21:0,21,209 0/0:22,0:22:60:0,60,900 1/1:0,22:22:66:810,66,0 0/0:10,0:10:21:0,21,315 0/0:20,0:20:48:0,48,720 0/0:16,0:16:33:0,33,495 0/0:11,0:11:27:0,27,404 0/0:25,0:25:72:0,72,1080 0/0:14,0:14:27:0,27,405 0/0:15,0:15:26:0,26,450 0/0:25,0:25:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:10,0:10:24:0,24,360 0/0:29,0:29:69:0,69,1035 0/0:6,0:6:9:0,9,135 0/1:10,12:22:99:322,0,294 0/0:16,0:16:33:0,33,495 0/0:14,0:14:25:0,25,475 0/0:11,0:11:24:0,24,360 0/0:23,0:23:60:0,60,821 0/0:9,0:9:24:0,24,360 0/0:11,0:11:20:0,20,360 0/0:14,0:14:27:0,27,405 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,305 0/0:10,0:10:21:0,21,315 0/0:8,0:8:21:0,21,286 0/0:15,0:15:33:0,33,495 0/1:11,5:16:99:139,0,351 0/0:9,0:9:21:0,21,315 0/0:24,0:24:57:0,57,855 0/0:42,0:42:88:0,88,1480 0/0:32,0:32:72:0,72,1080 0/0:25,0:25:63:0,63,945 0/0:32,0:32:65:0,65,1150 0/0:38,0:38:90:0,90,1350 0/0:30,0:30:63:0,63,945 0/0:11,0:11:24:0,24,360 0/0:10,0:10:24:0,24,318 0/0:38,0:38:93:0,93,1395 0/0:25,0:25:60:0,60,900 0/0:11,0:11:24:0,24,360 0/0:11,0:11:24:0,24,360 0/1:5,7:12:99:234,0,113 0/1:8,7:15:99:215,0,253 +20 17617204 . G A 6060.70 VQSRTrancheSNP99.60to99.80 NEGATIVE_TRAIN_SITE;HWP=1.0;AC=5;culprit=FS;MQ0=0;ReadPosRankSum=-0.159;AN=200;InbreedingCoeff=-0.0748;AF=0.002877;GQ_STDDEV=93.13;FS=22.312;DP=49348;GQ_MEAN=69.96;VQSLOD=-3.985;ClippingRankSum=0.343;BaseQRankSum=2.29;MLEAF=0.002877;MLEAC=5;MQ=59.49;QD=12.57;MQRankSum=0.098;CCC=1738;NCC=1 GT:AD:DP:GQ:PL 0/0:46,0:46:99:0,105,1575 0/0:38,0:38:84:0,84,1260 0/0:41,0:41:84:0,84,1260 0/0:49,0:49:99:0,111,1665 0/1:54,43:97:99:1113,0,1324 0/1:60,51:111:99:1266,0,1459 0/0:48,0:48:99:0,117,1755 0/0:44,0:44:96:0,96,1440 0/0:43,0:43:99:0,99,1485 0/0:56,0:56:99:0,120,1800 0/1:41,31:88:99:783,0,1035 0/1:43,45:88:99:1206,0,1089 0/0:39,0:39:78:0,78,1170 0/0:35,0:35:87:0,87,1305 0/0:20,0:20:60:0,60,698 0/0:38,0:38:99:0,108,1620 0/0:36,0:36:96:0,96,1440 0/0:32,0:32:62:0,62,1072 0/0:27,0:27:72:0,72,1080 0/0:51,0:51:99:0,114,1710 0/0:40,0:40:82:0,82,1401 0/0:37,0:37:90:0,90,1350 0/0:43,0:43:99:0,102,1530 0/0:57,0:57:98:0,98,1800 0/0:59,0:59:72:0,72,1800 0/0:66,0:66:0:0,0,1599 0/0:59,0:59:0:0,0,1444 0/0:82,0:82:0:0,0,1477 0/0:64,0:64:92:0,92,1800 0/0:87,0:87:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/0:53,0:53:99:0,111,1665 0/0:79,0:79:83:0,83,1800 0/0:161,0:161:0:0,0,4504 0/1:49,65:114:99:1846,0,1291 0/0:34,0:34:75:0,75,1125 0/0:54,0:54:99:0,117,1755 0/0:32,0:32:84:0,84,1260 0/0:35,0:35:75:0,75,1125 0/0:66,0:66:53:0,53,1738 0/0:62,0:62:0:0,0,1523 0/0:72,0:72:0:0,0,1219 0/0:63,0:63:0:0,0,1637 0/0:69,0:69:0:0,0,1474 0/0:65,0:65:3:0,3,1651 0/0:78,0:78:0:0,0,1956 0/0:66,0:66:7:0,7,1694 0/0:83,0:83:0:0,0,1910 0/0:66,0:66:0:0,0,1709 0/0:73,0:73:42:0,42,2102 0/0:50,0:50:64:0,64,1800 0/0:51,0:51:0:0,0,1163 0/0:59,0:59:0:0,0,1455 0/0:48,0:48:0:0,0,1281 0/0:68,0:68:0:0,0,1601 0/0:36,0:36:0:0,0,797 0/0:78,0:78:0:0,0,1761 0/0:82,0:82:0:0,0,1873 0/0:83,0:83:11:0,11,2213 0/0:61,0:61:0:0,0,1376 0/0:54,0:54:38:0,38,1461 0/0:58,0:58:0:0,0,1314 0/0:97,0:97:99:0,120,1800 0/0:49,0:49:0:0,0,1135 0/0:60,0:60:0:0,0,1518 0/0:31,0:31:93:0,93,1119 0/0:35,0:35:0:0,0,924 0/0:42,0:42:0:0,0,1186 0/0:90,0:90:0:0,0,1925 0/0:31,0:31:24:0,24,948 0/0:67,0:67:30:0,30,1969 0/0:39,0:39:0:0,0,1025 0/0:68,0:68:0:0,0,1819 0/0:46,0:46:44:0,44,1381 0/0:48,0:48:0:0,0,1221 0/0:29,0:29:0:0,0,825 0/0:44,0:44:35:0,35,1369 0/0:58,0:58:0:0,0,1636 0/0:51,0:51:17:0,17,1465 0/0:60,0:60:24:0,24,1730 0/0:32,0:32:10:0,10,904 0/0:33,0:33:25:0,25,1004 0/0:26,0:26:18:0,18,780 0/0:39,0:39:74:0,74,1440 0/0:28,0:28:66:0,66,990 0/0:60,0:60:0:0,0,1492 0/0:39,0:39:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:111,0:111:0:0,0,2770 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:90:0,90,1350 0/0:43,0:43:9:0,9,1262 0/0:38,0:38:0:0,0,1026 0/0:60,0:60:99:0,120,1800 0/0:42,0:42:81:0,81,1215 0/0:37,0:37:6:0,6,1137 0/0:50,0:50:33:0,33,1474 0/0:34,0:34:0:0,0,905 0/0:46,0:46:52:0,52,1392 +20 17617297 rs144713154 C G 1274.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.124;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=41.16;FS=5.908;DP=42816;GQ_MEAN=99.02;VQSLOD=2.48;ClippingRankSum=-0.178;BaseQRankSum=0.968;MLEAF=5.747E-4;MLEAC=1;MQ=59.66;QD=17.23;DB;MQRankSum=0.427;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:46,0:46:99:0,105,1575 0/0:38,0:38:84:0,84,1260 0/0:41,0:41:84:0,84,1260 0/0:49,0:49:99:0,111,1665 0/0:43,0:43:96:0,96,1440 0/0:45,0:45:99:0,108,1620 0/0:48,0:48:99:0,117,1755 0/0:44,0:44:96:0,96,1440 0/0:43,0:43:99:0,99,1485 0/0:56,0:56:99:0,120,1800 0/0:46,0:46:87:0,87,1305 0/0:35,0:35:75:0,75,1125 0/0:39,0:39:78:0,78,1170 0/0:35,0:35:87:0,87,1305 0/0:20,0:20:60:0,60,698 0/0:38,0:38:99:0,108,1620 0/0:36,0:36:96:0,96,1440 0/0:32,0:32:62:0,62,1072 0/0:27,0:27:72:0,72,1080 0/0:51,0:51:99:0,114,1710 0/0:40,0:40:82:0,82,1401 0/0:37,0:37:90:0,90,1350 0/0:43,0:43:99:0,102,1530 0/0:57,0:57:98:0,98,1800 0/0:59,0:59:72:0,72,1800 0/0:40,0:40:92:0,92,1485 0/0:50,0:50:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:92:0,92,1800 0/0:87,0:87:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/0:53,0:53:99:0,111,1665 0/0:79,0:79:83:0,83,1800 0/0:94,0:94:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:34,0:34:75:0,75,1125 0/0:54,0:54:99:0,117,1755 0/0:32,0:32:84:0,84,1260 0/0:35,0:35:75:0,75,1125 0/0:65,0:65:99:0,120,1800 0/0:41,0:41:99:0,105,1575 0/0:46,0:46:99:0,102,1530 0/0:48,0:48:99:0,114,1710 0/0:42,0:42:99:0,99,1421 0/0:58,0:58:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:48,0:48:99:0,106,1710 0/0:50,0:50:64:0,64,1800 0/0:54,0:54:91:0,91,1800 0/0:46,0:46:99:0,105,1575 0/0:31,0:31:63:0,63,945 0/0:40,0:40:90:0,90,1350 0/0:31,0:31:75:0,75,1125 0/0:60,0:60:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:28,0:28:66:0,66,990 0/0:55,0:55:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:45,0:45:99:0,105,1620 0/0:41,0:41:90:0,90,1350 0/0:31,0:31:93:0,93,1119 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:53,0:53:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:37,0:37:75:0,75,1125 0/0:46,0:46:99:0,102,1530 0/0:45,0:45:99:0,99,1485 0/0:30,0:30:72:0,72,1080 0/0:37,0:37:87:0,87,1305 0/0:32,0:32:66:0,66,990 0/1:36,38:74:99:1325,0,1156 0/0:39,0:39:87:0,87,1305 0/0:35,0:35:69:0,69,1079 0/0:43,0:43:87:0,87,1539 0/0:35,0:35:61:0,61,945 0/0:28,0:28:72:0,72,1080 0/0:36,0:36:78:0,78,1170 0/0:39,0:39:74:0,74,1440 0/0:28,0:28:66:0,66,990 0/0:46,0:46:99:0,108,1620 0/0:39,0:39:87:0,87,1305 0/0:29,0:29:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:79,0:79:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:45,0:45:90:0,90,1350 0/0:33,0:33:90:0,90,1350 0/0:30,0:30:66:0,66,990 0/0:60,0:60:99:0,120,1800 0/0:42,0:42:81:0,81,1215 0/0:27,0:27:60:0,60,900 0/0:32,0:32:69:0,69,1035 0/0:29,0:29:66:0,66,990 0/0:36,0:36:78:0,78,1170 +20 17622429 rs2236255 A G 428796.00 PASS HWP=3.0E-4;AC=25;culprit=QD;MQ0=0;ReadPosRankSum=0.382;AN=200;InbreedingCoeff=0.1335;AF=0.16;GQ_STDDEV=596.4;FS=1.148;DP=72818;GQ_MEAN=426.71;POSITIVE_TRAIN_SITE;VQSLOD=6.13;ClippingRankSum=0.041;BaseQRankSum=-0.507;MLEAF=0.16;MLEAC=279;MQ=59.71;QD=15.33;DB;MQRankSum=0.157;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:75,0:75:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/1:77,70:147:99:2062,0,2120 0/1:74,53:127:99:1377,0,2044 0/0:48,0:48:99:0,120,1800 0/1:71,64:135:99:1731,0,2056 0/0:74,0:74:99:0,120,1800 0/1:60,53:113:99:1359,0,1651 0/0:51,0:51:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1680 0/0:78,0:78:99:0,120,1800 0/1:40,33:73:99:916,0,1228 0/0:58,0:58:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/1:102,62:164:99:1684,0,3150 0/0:69,0:69:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/1:41,36:77:99:1019,0,1215 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/1:66,50:116:99:1358,0,1984 0/1:45,38:83:99:1046,0,1330 0/0:91,0:91:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/1:47,40:87:99:997,0,1431 0/0:109,0:109:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/1:49,52:101:99:1482,0,1499 0/1:29,18:47:99:524,0,821 0/0:28,0:28:69:0,69,1035 0/0:114,0:114:99:0,120,1800 0/0:45,0:45:99:0,108,1620 0/1:44,42:86:99:1182,0,1251 0/0:41,0:41:99:0,102,1530 0/0:87,0:87:99:0,120,1800 0/1:34,27:61:99:748,0,923 0/0:39,0:39:99:0,99,1485 0/0:32,0:32:68:0,68,1080 0/0:42,0:42:94:0,94,1451 0/0:45,0:45:99:0,110,1800 0/0:35,0:35:87:0,87,1226 0/0:47,0:47:99:0,120,1800 0/0:28,0:28:78:0,78,1170 0/1:18,20:38:99:628,0,463 0/0:26,0:26:72:0,72,1080 0/0:59,0:59:99:0,120,1800 0/1:32,32:64:99:934,0,939 0/0:64,0:64:99:0,120,1800 0/1:94,75:169:99:1865,0,2450 0/0:69,0:69:99:0,120,1800 0/1:30,54:84:99:1473,0,832 0/0:99,0:99:99:0,120,1800 0/1:136,81:217:99:2014,0,3336 0/1:82,69:151:99:1712,0,2166 0/0:57,0:57:99:0,117,1755 0/0:49,0:49:99:0,120,1800 1/1:1,126:127:99:4248,345,0 0/0:95,0:95:99:0,120,1800 0/0:43,0:43:87:0,87,1305 1/1:0,49:49:99:1712,146,0 0/1:22,24:46:99:698,0,650 0/0:50,0:50:99:0,120,1800 +20 17622471 rs144765063 C T 8706.93 PASS HWP=1.0;AC=4;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.104;AN=200;InbreedingCoeff=-0.0029;AF=0.002874;GQ_STDDEV=128.78;FS=2.479;DP=63687;GQ_MEAN=125.55;POSITIVE_TRAIN_SITE;VQSLOD=4.26;ClippingRankSum=0.311;BaseQRankSum=-0.027;MLEAF=0.002874;MLEAC=5;MQ=59.74;QD=13.31;DB;MQRankSum=0.104;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:75,0:75:99:0,120,1800 0/1:89,57:146:99:1595,0,2473 0/0:65,0:65:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/1:68,71:139:99:2104,0,2023 0/0:83,0:83:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/1:98,96:194:99:2623,0,2774 0/0:66,0:66:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1680 0/0:78,0:78:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:110,0:110:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:28,0:28:69:0,69,1035 0/0:114,0:114:99:0,120,1800 0/0:45,0:45:99:0,108,1620 0/0:81,0:81:99:0,120,1800 0/0:41,0:41:99:0,102,1530 0/0:87,0:87:99:0,120,1800 0/0:47,0:47:99:0,114,1710 0/0:39,0:39:99:0,99,1485 0/0:32,0:32:68:0,68,1080 0/0:42,0:42:94:0,94,1451 0/0:45,0:45:99:0,110,1800 0/0:35,0:35:87:0,87,1226 0/0:47,0:47:99:0,120,1800 0/0:28,0:28:78:0,78,1170 0/0:36,0:36:63:0,63,1215 0/0:26,0:26:72:0,72,1080 0/0:59,0:59:99:0,120,1800 0/1:42,40:82:99:1142,0,1371 0/0:64,0:64:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:62,0:62:99:0,111,1665 0/0:61,0:61:99:0,120,1800 0/0:57,0:57:99:0,117,1755 0/0:49,0:49:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:43,0:43:87:0,87,1305 0/0:49,0:49:99:0,114,1710 0/0:44,0:44:99:0,111,1665 0/0:50,0:50:99:0,120,1800 +20 17622495 rs34537635 T C 36777.80 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.627;AN=200;InbreedingCoeff=-0.0134;AF=0.013;GQ_STDDEV=255.17;FS=0.528;DP=64511;GQ_MEAN=156.03;POSITIVE_TRAIN_SITE;VQSLOD=4.32;ClippingRankSum=-0.592;BaseQRankSum=2.37;MLEAF=0.013;MLEAC=23;MQ=59.85;QD=11.69;DB;MQRankSum=0.321;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:75,0:75:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1680 0/0:78,0:78:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/1:60,42:102:99:1197,0,1834 0/0:45,0:45:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:110,0:110:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:28,0:28:69:0,69,1035 0/0:114,0:114:99:0,120,1800 0/0:45,0:45:99:0,108,1620 0/0:81,0:81:99:0,120,1800 0/0:41,0:41:99:0,102,1530 0/0:87,0:87:99:0,120,1800 0/0:47,0:47:99:0,114,1710 0/0:39,0:39:99:0,99,1485 0/0:32,0:32:68:0,68,1080 0/0:42,0:42:94:0,94,1451 0/0:45,0:45:99:0,110,1800 0/0:35,0:35:87:0,87,1226 0/0:47,0:47:99:0,120,1800 0/0:28,0:28:78:0,78,1170 0/0:36,0:36:63:0,63,1215 0/0:26,0:26:72:0,72,1080 0/0:59,0:59:99:0,120,1800 0/0:45,0:45:99:0,117,1755 0/0:64,0:64:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:62,0:62:99:0,111,1665 0/0:61,0:61:99:0,120,1800 0/0:57,0:57:99:0,117,1755 0/0:49,0:49:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:95,0:95:99:0,120,1800 0/0:43,0:43:87:0,87,1305 0/0:49,0:49:99:0,114,1710 0/0:44,0:44:99:0,111,1665 0/0:50,0:50:99:0,120,1800 +20 17622505 . T C 1466.69 PASS HWP=1.0;AC=1;culprit=MQRankSum;MQ0=0;ReadPosRankSum=-0.306;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=48.58;FS=8.572;DP=62997;GQ_MEAN=118.01;VQSLOD=-0.1454;ClippingRankSum=-0.012;BaseQRankSum=3.15;MLEAF=5.747E-4;MLEAC=1;MQ=59.71;QD=11.55;MQRankSum=-2.33;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:75,0:75:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:88,0:88:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:118,0:118:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:124,0:124:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1680 0/0:78,0:78:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:45,0:45:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:110,0:110:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:91,0:91:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:109,0:109:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:103,0:103:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:28,0:28:69:0,69,1035 0/0:114,0:114:99:0,120,1800 0/0:45,0:45:99:0,108,1620 0/0:81,0:81:99:0,120,1800 0/0:41,0:41:99:0,102,1530 0/0:87,0:87:99:0,120,1800 0/0:47,0:47:99:0,114,1710 0/0:39,0:39:99:0,99,1485 0/0:32,0:32:68:0,68,1080 0/0:42,0:42:94:0,94,1451 0/0:45,0:45:99:0,110,1800 0/0:35,0:35:87:0,87,1226 0/0:47,0:47:99:0,120,1800 0/0:28,0:28:78:0,78,1170 0/0:36,0:36:63:0,63,1215 0/0:26,0:26:72:0,72,1080 0/0:59,0:59:99:0,120,1800 0/0:45,0:45:99:0,117,1755 0/0:64,0:64:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/0:62,0:62:99:0,111,1665 0/0:61,0:61:99:0,120,1800 0/0:57,0:57:99:0,117,1755 0/0:49,0:49:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/1:74,53:127:99:1517,0,1965 0/0:43,0:43:87:0,87,1305 0/0:49,0:49:99:0,114,1710 0/0:44,0:44:99:0,111,1665 0/0:50,0:50:99:0,120,1800 +20 17623789 . A G 1449.38 PASS HWP=1.0;AC=1;culprit=MQ;MQ0=0;ReadPosRankSum=0.696;AN=200;InbreedingCoeff=-0.0036;AF=0.002299;GQ_STDDEV=26.61;FS=8.241;DP=18337;GQ_MEAN=49.53;VQSLOD=2.11;ClippingRankSum=0.776;BaseQRankSum=1.35;MLEAF=0.002299;MLEAC=4;MQ=60.0;QD=12.6;MQRankSum=0.913;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,843 0/0:27,0:27:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:31,0:31:78:0,78,1170 0/0:25,0:25:60:0,60,900 0/0:14,0:14:27:0,27,405 0/0:12,0:12:30:0,30,450 0/0:12,0:12:24:0,24,360 0/0:27,0:27:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:32,0:32:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,831 0/0:9,0:9:21:0,21,315 0/0:25,0:25:57:0,57,855 0/0:21,0:21:60:0,60,739 0/0:11,0:11:27:0,27,405 0/0:15,0:15:23:0,23,578 0/0:39,0:39:60:0,60,900 0/0:41,0:41:99:0,99,1485 0/0:13,0:13:21:0,21,315 0/0:13,0:13:20:0,20,360 0/0:23,0:23:60:0,60,840 0/0:26,0:26:69:0,69,1035 0/0:26,0:26:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:26,0:26:65:0,65,990 0/0:17,0:17:30:0,30,540 0/0:28,0:28:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:4,0:4:9:0,9,135 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,796 0/0:11,0:11:21:0,21,315 0/0:11,0:11:21:0,21,315 0/0:9,0:9:24:0,24,360 0/0:14,0:14:30:0,30,450 0/0:14,0:14:33:0,33,495 0/0:25,0:25:60:0,60,900 0/0:14,0:14:21:0,21,315 0/0:24,0:24:66:0,66,990 0/0:14,0:14:27:0,27,405 0/0:12,0:12:23:0,23,405 0/0:24,0:24:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:15,0:15:36:0,36,540 0/1:16,9:25:99:238,0,518 0/0:13,0:13:30:0,30,450 0/0:12,0:12:27:0,27,405 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,811 0/0:26,0:26:60:0,60,823 0/0:22,0:22:60:0,60,900 0/0:10,0:10:24:0,24,360 0/0:11,0:11:30:0,30,450 0/0:15,0:15:21:0,21,315 0/0:10,0:10:21:0,21,315 0/0:30,0:30:60:0,60,900 0/0:11,0:11:21:0,21,360 0/0:15,0:15:33:0,33,494 0/0:12,0:12:27:0,27,405 0/0:14,0:14:24:0,24,360 0/0:13,0:13:30:0,30,450 0/0:30,0:30:60:0,60,900 0/0:13,0:13:24:0,24,360 0/0:18,0:18:42:0,42,630 0/0:14,0:14:21:0,21,315 0/0:27,0:27:60:0,60,900 0/0:9,0:9:21:0,21,315 0/0:15,0:15:23:0,23,467 0/0:10,0:10:21:0,21,315 0/0:13,0:13:30:0,30,435 0/0:26,0:26:60:0,60,818 0/0:6,0:6:15:0,15,225 0/0:29,0:29:63:0,63,945 0/0:9,0:9:21:0,21,315 0/0:6,0:6:9:0,9,135 0/0:4,0:4:9:0,9,135 0/0:13,0:13:27:0,27,405 0/0:8,0:8:24:0,24,324 0/0:10,0:10:24:0,24,360 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:13,0:13:21:0,21,315 0/0:32,0:32:66:0,66,990 0/0:28,0:28:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:17,0:17:20:0,20,567 0/0:10,0:10:21:0,21,315 0/0:29,0:29:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:10,0:10:24:0,24,360 0/0:25,0:25:60:0,60,900 0/0:11,0:11:21:0,21,315 0/0:12,0:12:21:0,21,315 +20 17639366 rs73092300 T C 40936.90 PASS HWP=1.0;AC=17;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.166;AN=200;InbreedingCoeff=-0.0187;AF=0.018;GQ_STDDEV=242.26;FS=1.228;DP=25059;GQ_MEAN=104.3;POSITIVE_TRAIN_SITE;VQSLOD=4.3;ClippingRankSum=0.516;BaseQRankSum=-1.957;MLEAF=0.018;MLEAC=32;MQ=59.68;QD=14.16;DB;MQRankSum=0.558;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:29,0:29:69:0,69,946 0/0:24,0:24:60:0,60,900 0/0:30,0:30:65:0,65,1080 0/1:21,25:46:99:712,0,675 0/0:39,0:39:74:0,74,1170 0/1:51,45:96:99:1317,0,1541 0/0:28,0:28:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:25,0:25:60:0,60,900 0/1:43,24:67:99:665,0,1369 0/0:29,0:29:66:0,66,990 0/1:35,28:63:99:847,0,1092 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,815 0/0:27,0:27:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:29,0:29:69:0,69,1035 0/1:42,37:79:99:1001,0,1326 0/0:27,0:27:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:28,0:28:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/1:43,34:77:99:952,0,1422 0/1:42,62:104:99:1693,0,1208 0/0:33,0:33:75:0,75,1125 0/1:41,50:91:99:1377,0,1256 0/1:51,41:92:99:1147,0,1510 0/0:25,0:25:66:0,66,990 0/0:28,0:28:63:0,63,945 0/0:29,0:29:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:40,0:40:78:0,78,1350 0/1:66,96:162:99:2823,0,1915 0/0:28,0:28:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:23,0:23:61:0,61,990 0/0:25,0:25:60:0,60,900 0/0:23,0:23:66:0,66,990 0/1:32,31:63:99:827,0,994 0/1:32,43:75:99:1275,0,902 0/0:23,0:23:60:0,60,900 0/0:33,0:33:74:0,74,1170 0/1:45,47:92:99:1331,0,1414 0/0:27,0:27:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:29,0:29:75:0,75,1125 0/0:32,0:32:81:0,81,1215 0/1:58,54:112:99:1614,0,1869 0/0:31,0:31:90:0,90,1350 0/0:30,0:30:78:0,78,1170 0/0:29,0:29:63:0,63,945 0/0:31,0:31:69:0,69,1080 0/0:30,0:30:66:0,66,1035 0/0:25,0:25:63:0,63,945 0/0:28,0:28:75:0,75,1125 0/0:32,0:32:62:0,62,1170 0/0:26,0:26:60:0,60,900 0/0:33,0:33:67:0,67,1080 0/0:24,0:24:60:0,60,900 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:32,0:32:66:0,66,990 0/0:29,0:29:66:0,66,990 0/0:24,0:24:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:32,0:32:75:0,75,1125 0/1:68,73:141:99:2273,0,2111 0/0:26,0:26:62:0,62,1035 0/0:29,0:29:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:29,0:29:69:0,69,1035 0/0:27,0:27:63:0,63,945 0/1:27,28:55:99:821,0,839 0/1:43,35:78:99:1051,0,1332 0/0:26,0:26:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:29,0:29:67:0,67,1170 0/0:29,0:29:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:31,0:31:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:20,0:20:60:0,60,771 0/0:23,0:23:60:0,60,900 0/0:30,0:30:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,826 0/0:21,0:21:60:0,60,881 0/0:28,0:28:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:30,0:30:81:0,81,1215 +20 17640009 rs13040917 A C 13189.30 PASS NEGATIVE_TRAIN_SITE;HWP=1.0;AC=6;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.731;AN=6;InbreedingCoeff=-0.022;AF=1.0;GQ_STDDEV=6.06;FS=0.0;DP=651;GQ_MEAN=16.04;POSITIVE_TRAIN_SITE;VQSLOD=-0.5227;ClippingRankSum=0.731;BaseQRankSum=1.5;MLEAF=1.0;MLEAC=148;MQ=53.24;QD=32.73;DB;MQRankSum=-0.198;CCC=148;NCC=796 GT:AD:DP:GQ:PL ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:8,0:8:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,4:4:12:152,12,0 ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:4,0:4:.:. ./.:2,0:2:.:. ./.:3,0:3:.:. ./.:2,0:2:.:. ./.:4,0:4:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,4:4:12:119,12,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,5:5:15:157,15,0 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:4,0:4:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 17640833 . A C 180.62 VQSRTrancheSNP99.95to100.00 HWP=1.0;AC=3;culprit=FS;MQ0=0;ReadPosRankSum=-2.454;AN=196;InbreedingCoeff=-0.0644;AF=0.00289;GQ_STDDEV=26.17;FS=119.861;DP=17313;GQ_MEAN=38.0;VQSLOD=-138.7;ClippingRankSum=2.74;BaseQRankSum=-3.191;MLEAF=0.003468;MLEAC=6;MQ=57.97;QD=2.03;MQRankSum=-0.818;CCC=1730;NCC=5 GT:AD:DP:GQ:PL 0/0:18,0:18:35:0,35,675 0/0:23,0:23:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:20,0:20:60:0,60,752 0/0:24,0:24:60:0,60,900 0/0:10,0:10:24:0,24,360 0/0:23,0:23:60:0,60,852 0/0:29,0:29:60:0,60,900 0/0:30,0:30:48:0,48,947 0/0:11,0:11:30:0,30,395 0/0:11,0:11:24:0,24,360 0/0:8,0:8:21:0,21,315 0/0:29,0:29:60:0,60,900 0/0:22,0:22:25:0,25,646 0/0:25,0:25:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:23,0:23:60:0,60,876 0/0:24,0:24:36:0,36,540 0/0:25,0:25:60:0,60,900 0/0:18,0:18:0:0,0,436 ./.:10,0:10:.:. 0/0:11,0:11:0:0,0,222 0/0:24,0:24:62:0,62,825 0/0:21,0:21:60:0,60,821 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:0:0,0,525 0/0:33,0:33:0:0,0,714 0/0:23,0:23:0:0,0,343 0/0:22,0:22:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:10,0:10:21:0,21,315 0/0:13,0:13:0:0,0,101 0/0:13,0:13:28:0,28,450 0/0:18,0:18:0:0,0,377 0/0:13,0:13:0:0,0,304 0/0:14,0:14:20:0,20,394 0/0:9,0:9:0:0,0,130 0/0:16,0:16:18:0,18,478 0/0:13,0:13:0:0,0,273 0/0:18,0:18:0:0,0,471 0/0:18,0:18:0:0,0,283 0/0:19,0:19:7:0,7,516 0/1:12,11:23:76:76,0,331 0/0:21,0:21:0:0,0,457 0/0:12,0:12:0:0,0,102 0/0:16,0:16:0:0,0,395 0/0:13,0:13:36:0,36,537 0/0:10,0:10:0:0,0,223 0/0:14,0:14:0:0,0,310 0/0:21,0:21:0:0,0,476 0/0:18,0:18:5:0,5,470 0/0:24,0:24:0:0,0,212 0/0:12,0:12:0:0,0,252 0/0:25,0:25:64:0,64,793 0/1:11,9:20:68:68,0,326 0/0:27,0:27:0:0,0,550 0/0:9,0:9:0:0,0,98 0/0:9,0:9:13:0,13,228 0/0:25,0:25:60:0,60,900 0/0:7,0:7:8:0,8,180 0/0:7,0:7:0:0,0,77 0/0:21,0:21:0:0,0,519 0/0:9,0:9:4:0,4,206 0/0:14,0:14:0:0,0,279 0/0:8,0:8:0:0,0,137 0/0:22,0:22:0:0,0,352 0/0:10,0:10:0:0,0,49 0/0:11,0:11:0:0,0,151 ./.:6,0:6:.:. 0/0:16,0:16:0:0,0,286 0/0:7,0:7:1:0,1,201 0/0:14,0:14:17:0,17,427 0/0:14,0:14:0:0,0,339 0/0:11,0:11:0:0,0,116 0/0:12,0:12:0:0,0,269 0/0:8,0:8:0:0,0,165 0/0:16,0:16:0:0,0,290 0/0:14,0:14:0:0,0,205 0/0:13,0:13:20:0,20,347 0/0:24,0:24:60:0,60,900 0/0:22,0:22:63:0,63,864 0/0:12,0:12:33:0,33,495 0/0:30,0:30:0:0,0,526 0/0:28,0:28:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:13,0:13:0:0,0,252 0/0:6,0:6:0:0,0,156 0/0:30,0:30:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:11,0:11:0:0,0,194 0/0:14,0:14:0:0,0,146 0/0:6,0:6:0:0,0,170 0/1:8,5:13:66:66,0,492 +20 17705664 rs2296905 G A 747280.00 PASS HWP=0.0692;AC=69;culprit=FS;MQ0=0;ReadPosRankSum=0.951;AN=200;InbreedingCoeff=0.0647;AF=0.241;GQ_STDDEV=663.13;FS=0.642;DP=66035;GQ_MEAN=553.63;POSITIVE_TRAIN_SITE;VQSLOD=4.39;ClippingRankSum=-0.353;BaseQRankSum=2.95;MLEAF=0.241;MLEAC=420;MQ=59.61;QD=18.57;DB;MQRankSum=0.101;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:51,33:84:99:912,0,1398 0/1:44,27:71:99:748,0,1173 0/1:51,42:93:99:1289,0,1323 0/1:41,53:94:99:1510,0,1063 0/0:43,0:43:99:0,114,1710 0/1:58,48:106:99:1407,0,1473 0/1:47,37:84:99:1078,0,1229 0/1:48,53:101:99:1527,0,1317 0/1:52,44:96:99:1271,0,1540 0/1:43,45:88:99:1285,0,1206 0/0:45,0:45:99:0,108,1684 0/1:44,42:86:99:1238,0,1235 0/1:42,52:94:99:1667,0,1078 1/1:0,85:85:99:3092,256,0 0/1:17,29:46:99:927,0,420 0/1:39,58:97:99:1681,0,1024 0/0:38,0:38:99:0,108,1620 1/1:1,118:119:99:4123,324,0 0/1:39,53:92:99:1484,0,1059 0/0:39,0:39:99:0,105,1575 0/0:39,0:39:99:0,108,1620 0/0:40,0:40:99:0,108,1620 0/0:44,0:44:99:0,120,1800 0/1:145,141:286:99:4363,0,4071 1/1:0,259:259:99:9305,778,0 0/0:56,0:56:99:0,120,1800 0/1:63,49:112:99:1457,0,1695 1/1:0,118:118:99:4084,355,0 0/0:45,0:45:99:0,119,1800 0/1:44,63:107:99:1877,0,1213 0/1:35,38:73:99:1027,0,952 0/0:46,0:46:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/1:85,88:173:99:2542,0,2456 0/0:96,0:96:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/1:61,106:167:99:2974,0,1660 0/0:56,0:56:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/1:55,62:117:99:1959,0,1410 0/1:40,38:78:99:1129,0,1126 0/1:33,43:76:99:1264,0,861 0/0:45,0:45:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/1:51,58:109:99:1688,0,1372 0/0:74,0:74:99:0,120,1800 0/1:45,58:103:99:1796,0,1225 0/0:62,0:62:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/1:60,82:142:99:2519,0,1705 0/1:48,55:103:99:1699,0,1382 0/0:42,0:42:99:0,105,1575 0/1:51,53:104:99:1677,0,1312 0/0:30,0:30:82:0,82,1152 0/1:53,56:109:99:1663,0,1495 0/0:60,0:60:99:0,120,1800 0/0:99,0:99:99:0,120,1800 0/1:60,63:123:99:1919,0,1705 0/0:68,0:68:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:88,0:88:99:0,120,1800 1/1:0,112:112:99:4066,337,0 0/0:53,0:53:99:0,120,1800 1/1:0,111:111:99:3903,334,0 0/1:35,36:71:99:1001,0,1083 0/1:21,29:50:99:895,0,586 0/1:83,69:152:99:2113,0,2390 0/1:38,29:67:99:800,0,1069 0/0:54,0:54:99:0,120,1800 0/0:30,0:30:81:0,81,1215 0/0:64,0:64:99:0,120,1800 0/0:22,0:22:60:0,60,900 0/0:36,0:36:84:0,84,1297 0/1:23,27:50:99:797,0,628 0/1:42,39:81:99:1179,0,1232 0/0:33,0:33:87:0,87,1305 0/0:38,0:38:99:0,108,1478 0/0:38,0:38:99:0,102,1530 0/0:28,0:28:69:0,69,1035 0/0:21,0:21:60:0,60,900 0/1:27,31:58:99:998,0,784 0/1:43,47:90:99:1387,0,1214 0/1:25,32:57:99:954,0,730 1/1:0,141:141:99:5036,424,0 0/1:44,81:125:99:2332,0,1082 0/1:55,76:131:99:2253,0,1436 0/1:61,56:117:99:1646,0,1673 0/0:87,0:87:99:0,120,1800 1/1:4,187:191:99:6219,518,0 0/1:68,75:143:99:2075,0,1724 0/1:38,43:81:99:1219,0,1132 1/1:0,73:73:99:2558,219,0 0/0:58,0:58:99:0,120,1800 0/1:58,47:105:99:1372,0,1568 0/1:26,27:53:99:755,0,752 0/1:37,39:76:99:1274,0,1119 1/1:0,57:57:99:2008,171,0 1/1:0,73:73:99:2584,220,0 +20 17705677 rs4814640 A G 3212960.00 PASS HWP=0.0903;AC=197;culprit=FS;MQ0=0;ReadPosRankSum=0.614;AN=200;InbreedingCoeff=0.0702;AF=0.937;GQ_STDDEV=454.83;FS=0.577;DP=106189;GQ_MEAN=492.43;POSITIVE_TRAIN_SITE;VQSLOD=4.28;ClippingRankSum=-0.302;BaseQRankSum=-1.254;MLEAF=0.937;MLEAC=1631;MQ=59.61;QD=30.41;DB;MQRankSum=0.151;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 1/1:1,87:88:99:2903,258,0 1/1:0,77:77:99:2482,231,0 1/1:0,111:111:99:3704,334,0 1/1:0,98:98:99:3217,294,0 1/1:0,83:83:99:2761,249,0 1/1:1,117:118:99:3866,348,0 1/1:1,95:96:99:3159,283,0 1/1:0,106:106:99:3498,318,0 1/1:0,108:108:99:3759,324,0 1/1:0,109:109:99:3640,327,0 1/1:2,94:96:99:3154,276,0 1/1:0,100:100:99:3271,300,0 1/1:0,104:104:99:3637,312,0 1/1:0,102:102:99:3328,306,0 1/1:0,47:47:99:1534,141,0 1/1:1,102:103:99:3279,269,0 0/1:43,47:90:99:1297,0,1162 1/1:0,128:128:99:4192,384,0 1/1:0,102:102:99:3303,306,0 1/1:0,116:116:99:3815,348,0 1/1:0,98:98:99:3220,295,0 1/1:0,111:111:99:3549,333,0 1/1:0,111:111:99:3662,334,0 1/1:0,332:332:99:11230,993,0 1/1:0,301:301:99:10125,904,0 1/1:0,90:90:99:2916,271,0 1/1:0,123:123:99:3936,369,0 1/1:0,117:117:99:3794,351,0 1/1:0,98:98:99:3115,292,0 1/1:0,122:122:99:4244,366,0 1/1:0,82:82:99:2676,246,0 1/1:0,174:174:99:5703,522,0 1/1:0,179:179:99:6066,537,0 1/1:0,195:195:99:6568,585,0 1/1:2,164:166:99:5557,464,0 0/1:108,73:181:99:1781,0,2884 1/1:0,200:200:99:6467,600,0 1/1:0,101:101:99:3299,303,0 1/1:1,94:95:99:3088,247,0 1/1:0,122:122:99:4075,366,0 1/1:0,83:83:99:2727,250,0 1/1:0,87:87:99:2832,262,0 1/1:0,103:103:99:3410,309,0 1/1:0,116:116:99:3769,348,0 1/1:0,124:124:99:4036,372,0 1/1:0,145:145:99:4843,436,0 1/1:0,115:115:99:3774,345,0 1/1:1,137:138:99:4327,374,0 1/1:0,149:149:99:5171,448,0 1/1:0,149:149:99:5276,448,0 1/1:0,120:120:99:4071,360,0 1/1:0,84:84:99:2753,252,0 1/1:0,113:113:99:3703,339,0 1/1:0,78:78:99:2694,233,0 1/1:0,131:131:99:4500,394,0 1/1:0,113:113:99:3735,339,0 1/1:0,157:157:99:5268,472,0 1/1:0,134:134:99:4428,402,0 1/1:0,147:147:99:4775,441,0 1/1:0,157:157:99:5378,472,0 1/1:0,89:89:99:2910,267,0 1/1:0,109:109:99:3562,327,0 1/1:0,197:197:99:6909,592,0 1/1:0,122:122:99:4011,365,0 1/1:0,97:97:99:3201,291,0 1/1:1,123:124:99:4058,342,0 1/1:0,75:75:99:2593,225,0 1/1:0,53:53:99:1879,159,0 1/1:0,167:167:99:5955,502,0 1/1:0,72:72:99:2460,216,0 1/1:1,104:105:99:3560,306,0 1/1:0,77:77:99:2742,232,0 1/1:1,147:148:99:4807,435,0 1/1:0,73:73:99:2538,220,0 1/1:0,84:84:99:2911,252,0 1/1:0,60:60:99:2131,180,0 1/1:0,92:92:99:3147,276,0 1/1:0,75:75:99:2609,225,0 0/1:42,37:79:99:1032,0,1247 1/1:0,78:78:99:2745,235,0 1/1:1,44:45:98:1580,98,0 1/1:0,53:53:99:1814,159,0 1/1:0,66:66:99:2331,198,0 1/1:0,108:108:99:3778,325,0 1/1:0,71:71:99:2505,213,0 1/1:0,147:147:99:4999,441,0 1/1:0,137:137:99:4414,411,0 1/1:0,143:143:99:4793,429,0 1/1:0,126:126:99:4097,378,0 1/1:0,172:172:99:5844,517,0 1/1:0,226:226:99:7370,679,0 1/1:0,149:149:99:4828,447,0 1/1:0,91:91:99:3170,273,0 1/1:0,80:80:99:2761,240,0 1/1:0,167:167:99:5316,502,0 1/1:0,130:130:99:4187,391,0 1/1:0,57:57:99:1910,171,0 1/1:0,86:86:99:3058,259,0 1/1:0,56:56:99:1975,168,0 1/1:0,81:81:99:2752,243,0 +20 17705709 . C T 2461.31 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.529;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=61.68;FS=1.544;DP=39907;GQ_MEAN=89.68;VQSLOD=2.39;ClippingRankSum=-0.646;BaseQRankSum=1.95;MLEAF=0.001149;MLEAC=2;MQ=59.41;QD=9.61;MQRankSum=1.54;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:84:0,84,1260 0/0:35,0:35:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:33,0:33:66:0,66,990 0/0:35,0:35:78:0,78,1170 0/0:36,0:36:90:0,90,1350 0/0:31,0:31:75:0,75,1125 0/0:32,0:32:78:0,78,1098 0/0:47,0:47:99:0,108,1620 0/0:42,0:42:93:0,93,1395 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:84,0:84:99:0,120,1800 0/0:43,0:43:84:0,84,1260 0/0:33,0:33:78:0,78,1170 0/0:93,0:93:99:0,120,1800 0/0:39,0:39:69:0,69,1035 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:78:0,78,1170 0/0:121,0:121:99:0,120,1800 0/0:40,0:40:84:0,84,1260 0/0:54,0:54:99:0,111,1665 0/0:41,0:41:75:0,75,1125 0/0:70,0:70:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:45,0:45:84:0,84,1260 0/0:52,0:52:99:0,99,1485 0/0:58,0:58:99:0,105,1575 0/0:45,0:45:90:0,90,1350 0/0:52,0:52:99:0,117,1755 0/0:29,0:29:63:0,63,945 0/0:109,0:109:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:44,0:44:93:0,93,1395 0/0:31,0:31:63:0,63,945 0/0:48,0:48:99:0,102,1530 0/0:39,0:39:87:0,87,1305 0/0:60,0:60:99:0,120,1800 0/0:34,0:34:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:40,0:40:78:0,78,1170 0/0:55,0:55:99:0,99,1485 0/0:44,0:44:99:0,102,1530 0/0:73,0:73:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/0:53,0:53:99:0,120,1800 0/0:42,0:42:87:0,87,1305 0/0:41,0:41:69:0,69,1035 0/0:38,0:38:72:0,72,1080 0/0:48,0:48:99:0,102,1530 0/0:46,0:46:99:0,105,1575 0/0:55,0:55:99:0,120,1800 0/0:50,0:50:99:0,105,1575 0/0:65,0:65:99:0,120,1800 0/0:41,0:41:99:0,99,1485 0/0:40,0:40:90:0,90,1350 0/0:38,0:38:87:0,87,1305 0/0:60,0:60:99:0,117,1755 0/0:47,0:47:99:0,102,1530 0/0:37,0:37:96:0,96,1440 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:50,0:50:99:0,108,1620 0/0:29,0:29:60:0,60,900 0/0:53,0:53:99:0,108,1620 0/0:33,0:33:84:0,84,1260 0/0:55,0:55:99:0,111,1665 0/0:31,0:31:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:27,0:27:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:35,0:35:62:0,62,1134 0/0:50,0:50:90:0,90,1350 0/1:115,63:178:99:1484,0,3150 0/0:28,0:28:60:0,60,900 0/0:58,0:58:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:33,0:33:60:0,60,900 0/0:32,0:32:69:0,69,1035 0/0:26,0:26:63:0,63,945 0/0:41,0:41:96:0,96,1440 0/0:92,0:92:99:0,120,1800 0/0:25,0:25:63:0,63,945 0/0:37,0:37:66:0,66,990 0/0:32,0:32:63:0,63,945 0/0:31,0:31:60:0,60,900 +20 17705793 rs1133096 T C 110597.00 PASS HWP=0.0078;AC=8;culprit=FS;MQ0=0;ReadPosRankSum=0.288;AN=200;InbreedingCoeff=0.1271;AF=0.036;GQ_STDDEV=340.81;FS=0.587;DP=39827;GQ_MEAN=166.19;POSITIVE_TRAIN_SITE;VQSLOD=4.44;ClippingRankSum=-0.076;BaseQRankSum=5.33;MLEAF=0.036;MLEAC=63;MQ=59.73;QD=17.72;DB;MQRankSum=0.76;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:84:0,84,1260 0/0:35,0:35:78:0,78,1170 0/0:29,0:29:66:0,66,990 0/0:33,0:33:66:0,66,990 0/0:35,0:35:78:0,78,1170 0/0:36,0:36:90:0,90,1350 0/0:31,0:31:75:0,75,1125 0/0:32,0:32:78:0,78,1098 0/0:47,0:47:99:0,108,1620 0/0:42,0:42:93:0,93,1395 0/0:28,0:28:60:0,60,900 0/0:29,0:29:66:0,66,990 0/1:50,32:82:99:1041,0,1524 0/0:43,0:43:84:0,84,1260 0/0:33,0:33:78:0,78,1170 0/1:55,35:90:99:1043,0,1597 0/0:39,0:39:69:0,69,1035 0/0:35,0:35:75:0,75,1125 0/0:32,0:32:78:0,78,1170 1/1:0,120:120:99:4271,361,0 0/0:40,0:40:84:0,84,1260 0/0:54,0:54:99:0,111,1665 0/0:41,0:41:75:0,75,1125 0/0:70,0:70:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:45,0:45:84:0,84,1260 0/0:52,0:52:99:0,99,1485 0/0:58,0:58:99:0,105,1575 0/0:45,0:45:90:0,90,1350 0/0:52,0:52:99:0,117,1755 0/0:29,0:29:63:0,63,945 1/1:0,108:108:99:3964,325,0 0/0:63,0:63:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:44,0:44:93:0,93,1395 0/0:31,0:31:63:0,63,945 0/0:48,0:48:99:0,102,1530 0/0:39,0:39:87:0,87,1305 0/0:60,0:60:99:0,120,1800 0/0:34,0:34:75:0,75,1125 0/0:28,0:28:63:0,63,945 0/0:40,0:40:78:0,78,1170 0/0:55,0:55:99:0,99,1485 0/0:44,0:44:99:0,102,1530 0/0:73,0:73:99:0,120,1800 0/0:58,0:58:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:41,0:41:93:0,93,1395 0/0:53,0:53:99:0,120,1800 0/0:42,0:42:87:0,87,1305 0/0:41,0:41:69:0,69,1035 0/0:38,0:38:72:0,72,1080 0/0:48,0:48:99:0,102,1530 0/0:46,0:46:99:0,105,1575 0/0:55,0:55:99:0,120,1800 0/0:50,0:50:99:0,105,1575 0/0:65,0:65:99:0,120,1800 0/0:41,0:41:99:0,99,1485 0/0:40,0:40:90:0,90,1350 0/0:38,0:38:87:0,87,1305 0/0:60,0:60:99:0,117,1755 0/0:47,0:47:99:0,102,1530 0/0:37,0:37:96:0,96,1440 0/0:30,0:30:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:50,0:50:99:0,108,1620 0/0:29,0:29:60:0,60,900 0/0:53,0:53:99:0,108,1620 0/0:33,0:33:84:0,84,1260 0/0:55,0:55:99:0,111,1665 0/0:31,0:31:69:0,69,1035 0/0:28,0:28:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:30,0:30:60:0,60,900 0/0:31,0:31:60:0,60,900 0/0:29,0:29:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:27,0:27:66:0,66,990 0/0:31,0:31:60:0,60,900 0/0:35,0:35:62:0,62,1134 0/0:50,0:50:90:0,90,1350 0/1:53,37:90:99:1181,0,1448 0/0:28,0:28:60:0,60,900 0/0:58,0:58:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:33,0:33:69:0,69,1035 0/0:33,0:33:60:0,60,900 0/0:32,0:32:69:0,69,1035 0/0:26,0:26:63:0,63,945 0/0:41,0:41:96:0,96,1440 0/1:39,53:92:99:1570,0,1028 0/0:25,0:25:63:0,63,945 0/0:37,0:37:66:0,66,990 0/0:32,0:32:63:0,63,945 0/0:31,0:31:60:0,60,900 +20 17716416 rs1053993 C G 891661.00 PASS HWP=0.3778;AC=95;culprit=QD;MQ0=0;ReadPosRankSum=0.555;AN=200;InbreedingCoeff=0.0317;AF=0.418;GQ_STDDEV=563.86;FS=1.094;DP=56788;GQ_MEAN=576.99;POSITIVE_TRAIN_SITE;VQSLOD=4.63;ClippingRankSum=-0.226;BaseQRankSum=-0.337;MLEAF=0.418;MLEAC=728;MQ=59.63;QD=19.94;DB;MQRankSum=0.069;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:49,37:86:99:1149,0,1537 0/1:28,31:59:99:924,0,934 0/1:37,38:75:99:1122,0,1201 0/1:51,31:82:99:847,0,1656 0/1:49,38:87:99:1099,0,1493 0/1:43,33:76:99:977,0,1328 0/1:44,35:79:99:1124,0,1475 0/1:40,28:68:99:790,0,1271 0/1:39,39:78:99:1122,0,1238 0/1:33,34:67:99:1033,0,946 0/1:36,31:67:99:978,0,1039 0/1:38,35:73:99:1011,0,1143 1/1:1,75:76:99:2830,226,0 1/1:2,57:59:99:2022,142,0 0/1:17,19:36:99:571,0,506 1/1:0,58:58:99:2058,174,0 1/1:0,54:54:99:1927,162,0 1/1:0,72:72:99:2584,216,0 0/1:33,19:52:99:514,0,995 0/0:37,0:37:84:0,84,1260 1/1:0,66:66:99:2308,198,0 0/0:33,0:33:77:0,77,1287 0/0:26,0:26:66:0,66,990 0/1:77,79:156:99:2559,0,2591 1/1:0,152:152:99:5774,455,0 1/1:0,52:52:99:1929,156,0 0/1:37,42:79:99:1295,0,1058 1/1:0,72:72:99:2670,216,0 0/0:36,0:36:87:0,87,1305 0/1:46,43:89:99:1393,0,1496 0/1:38,41:79:99:1339,0,1197 0/0:35,0:35:63:0,63,945 0/0:79,0:79:99:0,120,1800 0/1:98,63:161:99:1951,0,3464 0/1:65,61:126:99:1793,0,2099 1/1:0,96:96:99:3193,288,0 0/1:48,67:115:99:2145,0,1467 0/0:36,0:36:87:0,87,1305 0/0:35,0:35:79:0,79,1325 0/1:46,33:79:99:1005,0,1405 0/1:30,25:55:99:644,0,840 0/1:21,30:51:99:933,0,640 0/1:23,23:46:99:673,0,664 0/1:44,36:80:99:1040,0,1395 0/1:39,33:72:99:923,0,1295 0/0:56,0:56:99:0,120,1800 0/1:43,34:77:99:910,0,1352 0/1:47,35:82:99:989,0,1493 0/0:59,0:59:99:0,120,1800 0/1:56,49:105:99:1535,0,1788 0/1:47,37:84:99:1045,0,1433 0/1:40,27:67:99:830,0,1241 0/1:15,20:35:99:636,0,459 0/0:37,0:37:90:0,90,1350 0/1:53,37:90:99:1162,0,1667 0/0:50,0:50:99:0,120,1800 0/0:63,0:63:99:0,120,1800 1/1:0,87:87:99:3270,261,0 0/1:41,54:95:99:1560,0,1224 0/0:57,0:57:99:0,120,1800 0/0:40,0:40:99:0,105,1575 0/1:36,29:65:99:936,0,1008 0/1:80,75:155:99:2521,0,2697 1/1:0,72:72:99:2724,216,0 0/0:46,0:46:99:0,117,1755 1/1:0,60:60:99:2199,180,0 0/1:26,25:51:99:808,0,714 0/1:23,21:44:99:727,0,740 0/1:59,55:114:99:1683,0,1910 0/1:30,18:48:99:551,0,1064 0/1:62,36:98:99:1160,0,1911 0/1:27,33:60:99:980,0,890 0/0:50,0:50:99:0,120,1800 0/0:26,0:26:63:0,63,945 0/1:26,22:48:99:751,0,946 0/1:20,16:36:99:461,0,635 0/1:30,33:63:99:1097,0,1027 0/0:29,0:29:66:0,66,990 0/0:34,0:34:80:0,80,1305 0/0:30,0:30:63:0,63,990 0/0:28,0:28:69:0,69,1035 0/0:24,0:24:63:0,63,945 0/1:31,25:56:99:828,0,1019 0/1:38,33:71:99:1062,0,1356 0/1:26,23:49:99:771,0,792 1/1:1,87:88:99:3299,223,0 1/1:1,101:102:99:3456,265,0 0/1:45,44:89:99:1342,0,1441 0/1:28,27:55:99:824,0,861 0/0:66,0:66:99:0,120,1800 1/1:0,111:111:99:3938,333,0 0/1:56,43:99:99:1192,0,1720 0/1:29,28:57:99:874,0,1035 1/1:0,36:36:99:1378,108,0 0/0:46,0:46:93:0,93,1395 1/1:0,97:97:99:3260,291,0 0/1:21,27:48:99:812,0,692 0/1:35,38:73:99:1148,0,1038 1/1:0,38:38:99:1427,114,0 1/1:0,69:69:99:2630,207,0 +20 17923043 rs17349809 G A 86383.70 PASS HWP=0.0614;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.827;AN=200;InbreedingCoeff=0.0866;AF=0.038;GQ_STDDEV=301.75;FS=0.527;DP=37379;GQ_MEAN=160.28;POSITIVE_TRAIN_SITE;VQSLOD=1.41;ClippingRankSum=-0.124;BaseQRankSum=-2.31;MLEAF=0.038;MLEAC=66;MQ=58.48;QD=13.88;DB;MQRankSum=0.536;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:37,0:37:94:0,94,1363 0/0:29,0:29:81:0,81,1215 0/0:26,0:26:60:0,60,900 0/0:28,0:28:78:0,78,1170 0/0:32,0:32:75:0,75,1125 0/0:28,0:28:78:0,78,1111 0/0:53,0:53:99:0,118,1800 0/0:35,0:35:81:0,81,1215 0/0:34,0:34:93:0,93,1395 0/0:25,0:25:69:0,69,1035 0/0:31,0:31:84:0,84,1260 0/0:31,0:31:84:0,84,1260 0/0:48,0:48:99:0,120,1800 0/0:30,0:30:81:0,81,1177 0/0:24,0:24:60:0,60,900 0/0:30,0:30:90:0,90,1140 0/0:32,0:32:87:0,87,1305 0/0:32,0:32:93:0,93,1323 0/0:29,0:29:81:0,81,1152 0/0:41,0:41:99:0,120,1800 0/1:30,45:75:99:1298,0,841 0/0:36,0:36:96:0,96,1440 0/0:27,0:27:78:0,78,1170 0/0:74,0:74:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/1:71,40:111:99:1084,0,2219 0/0:59,0:59:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:39,0:39:66:0,66,990 0/0:25,0:25:61:0,61,977 0/0:22,0:22:60:0,60,900 0/0:29,0:29:87:0,87,1031 0/0:58,0:58:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:22,0:22:63:0,63,807 0/0:25,0:25:72:0,72,993 0/0:27,0:27:78:0,78,1170 0/0:47,0:47:99:0,108,1620 0/0:53,0:53:99:0,120,1800 0/0:40,0:40:99:0,99,1485 0/0:33,0:33:81:0,81,1215 0/0:33,0:33:99:0,99,1297 0/0:35,0:35:78:0,78,1170 0/0:46,0:46:99:0,117,1755 0/0:64,0:64:99:0,120,1800 0/0:43,0:43:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:55,0:55:99:0,120,1800 0/0:46,0:46:99:0,112,1800 0/0:50,0:50:99:0,120,1800 0/0:42,0:42:93:0,93,1395 0/0:40,0:40:99:0,99,1468 0/0:37,0:37:78:0,78,1170 0/0:64,0:64:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:44,0:44:99:0,108,1620 0/0:90,0:90:99:0,120,1800 0/0:40,0:40:87:0,87,1305 0/0:47,0:47:99:0,102,1530 0/0:36,0:36:99:0,102,1530 0/0:28,0:28:69:0,69,1035 0/0:29,0:29:61:0,61,1046 0/0:53,0:53:99:0,120,1800 0/0:30,0:30:72:0,72,1080 0/0:63,0:63:99:0,120,1800 0/0:36,0:36:96:0,96,1440 0/0:64,0:64:99:0,120,1800 0/0:32,0:32:72:0,72,1080 0/0:39,0:39:99:0,99,1485 0/0:28,0:28:81:0,81,1047 0/0:43,0:43:99:0,120,1800 0/0:38,0:38:90:0,90,1350 0/0:41,0:41:86:0,86,1716 0/0:43,0:43:99:0,107,1710 0/0:29,0:29:81:0,81,1215 0/0:26,0:26:72:0,72,1080 0/0:26,0:26:66:0,66,990 0/0:43,0:43:99:0,120,1800 0/0:35,0:35:99:0,99,1485 0/0:54,0:54:99:0,120,1800 0/0:28,0:28:81:0,81,1215 0/0:31,0:31:87:0,87,1305 0/0:31,0:31:87:0,87,1305 0/0:78,0:78:99:0,120,1800 0/0:37,0:37:93:0,93,1395 0/0:31,0:31:75:0,75,1125 0/0:37,0:37:96:0,96,1440 0/0:31,0:31:66:0,66,1260 0/0:32,0:32:90:0,90,1350 0/0:33,0:33:81:0,81,1215 0/0:25,0:25:63:0,63,926 0/0:33,0:33:61:0,61,1305 0/0:24,0:24:61:0,61,968 0/0:51,0:51:99:0,117,1755 +20 17923717 rs145873414 A C 49397.20 PASS HWP=0.1027;AC=8;culprit=MQ;MQ0=0;ReadPosRankSum=1.02;AN=200;InbreedingCoeff=0.1359;AF=0.008046;GQ_STDDEV=325.11;FS=0.644;DP=55837;GQ_MEAN=137.62;POSITIVE_TRAIN_SITE;VQSLOD=1.13;ClippingRankSum=-0.179;BaseQRankSum=4.28;MLEAF=0.008046;MLEAC=14;MQ=58.28;QD=18.06;DB;MQRankSum=0.808;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:56,0:56:99:0,120,1800 0/0:45,0:45:93:0,93,1395 0/0:45,0:45:96:0,96,1440 0/0:52,0:52:99:0,120,1800 0/1:104,89:193:99:2610,0,3044 0/1:127,113:240:99:3274,0,3488 0/0:59,0:59:99:0,108,1620 0/0:64,0:64:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/1:116,123:239:99:3389,0,3577 0/1:93,76:169:99:2342,0,2671 0/0:70,0:70:99:0,120,1800 0/0:58,0:58:99:0,114,1710 0/0:67,0:67:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:89,0:89:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:39,0:39:90:0,90,1350 0/0:46,0:46:93:0,93,1395 0/0:78,0:78:99:0,120,1800 0/0:97,0:97:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:83,0:83:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:177,0:177:99:0,120,1800 0/0:131,0:131:99:0,120,1800 0/1:150,156:306:99:5156,0,4425 0/0:29,0:29:60:0,60,900 0/0:40,0:40:81:0,81,1215 0/0:81,0:81:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:115,0:115:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/1:123,143:266:99:4569,0,3543 0/0:112,0:112:99:0,120,1800 0/0:120,0:120:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:127,0:127:99:0,120,1800 0/0:59,0:59:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:79,0:79:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:106,0:106:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:105,0:105:99:0,120,1800 1/1:2,335:337:99:13476,986,0 0/0:84,0:84:99:0,120,1800 0/0:96,0:96:99:0,120,1800 0/0:129,0:129:99:0,120,1800 0/0:86,0:86:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:90,0:90:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:34,0:34:81:0,81,1215 0/0:111,0:111:99:0,120,1800 0/0:47,0:47:93:0,93,1395 0/0:85,0:85:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:48,0:48:90:0,90,1350 0/0:53,0:53:99:0,120,1800 0/0:40,0:40:81:0,81,1215 0/0:54,0:54:99:0,111,1665 0/0:51,0:51:99:0,105,1575 0/0:58,0:58:99:0,120,1800 0/0:57,0:57:99:0,117,1755 0/0:37,0:37:90:0,90,1350 0/0:49,0:49:99:0,99,1485 0/0:45,0:45:99:0,99,1485 0/0:71,0:71:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:31,0:31:72:0,72,1080 0/0:30,0:30:63:0,63,945 0/0:82,0:82:99:0,120,1800 0/0:113,0:113:99:0,120,1800 0/0:26,0:26:60:0,60,900 0/0:42,0:42:87:0,87,1395 0/0:49,0:49:99:0,111,1665 0/0:39,0:39:72:0,72,1080 0/0:44,0:44:99:0,102,1530 0/0:26,0:26:60:0,60,900 0/0:35,0:35:69:0,69,1035 0/0:53,0:53:99:0,120,1800 0/0:54,0:54:99:0,105,1575 0/0:60,0:60:99:0,120,1800 +20 17932137 . C A 776.69 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=2.91;AN=200;InbreedingCoeff=-6.0E-4;AF=5.747E-4;GQ_STDDEV=29.94;FS=6.434;DP=28520;GQ_MEAN=78.99;VQSLOD=-0.11;ClippingRankSum=1.46;BaseQRankSum=-1.716;MLEAF=5.747E-4;MLEAC=1;MQ=58.13;QD=14.94;MQRankSum=2.25;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:24,0:24:66:0,66,990 0/0:26,0:26:69:0,69,1003 0/0:23,0:23:63:0,63,945 0/0:34,0:34:78:0,78,1170 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/0:41,0:41:93:0,93,1412 0/0:29,0:29:62:0,62,1035 0/0:35,0:35:85:0,85,1395 0/0:23,0:23:63:0,63,945 0/0:35,0:35:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/0:43,0:43:99:0,120,1800 0/0:31,0:31:90:0,90,1350 0/0:23,0:23:63:0,63,945 0/0:36,0:36:99:0,102,1530 0/0:29,0:29:81:0,81,1215 0/0:34,0:34:90:0,90,1350 0/0:26,0:26:60:0,60,900 0/0:36,0:36:81:0,81,1215 0/0:26,0:26:66:0,66,990 0/0:30,0:30:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:30,0:30:78:0,78,1170 0/0:30,0:30:87:0,87,1305 0/0:48,0:48:99:0,114,1710 0/0:37,0:37:93:0,93,1395 0/0:46,0:46:99:0,120,1800 0/0:28,0:28:66:0,66,990 0/0:27,0:27:66:0,66,957 0/0:29,0:29:62:0,62,1127 0/0:23,0:23:60:0,60,900 0/0:71,0:71:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:23,0:23:63:0,63,945 0/0:21,0:21:60:0,60,900 0/0:33,0:33:93:0,93,1132 0/0:33,0:33:84:0,84,1260 0/0:51,0:51:99:0,120,1800 0/0:38,0:38:79:0,79,1395 0/0:36,0:36:93:0,93,1395 0/0:45,0:45:99:0,120,1800 0/0:33,0:33:77:0,77,1215 0/0:40,0:40:99:0,108,1620 0/0:39,0:39:99:0,111,1487 0/0:47,0:47:96:0,96,1440 0/0:51,0:51:99:0,117,1755 0/0:36,0:36:99:0,102,1530 0/0:52,0:52:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/0:36,0:36:87:0,87,1305 0/0:30,0:30:69:0,69,1035 0/0:39,0:39:87:0,87,1305 0/0:43,0:43:99:0,99,1485 0/0:37,0:37:99:0,111,1373 0/0:50,0:50:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:45,0:45:99:0,111,1665 0/0:56,0:56:99:0,120,1800 0/0:38,0:38:93:0,93,1395 0/0:74,0:74:99:0,120,1800 0/0:39,0:39:90:0,90,1350 0/0:39,0:39:99:0,102,1530 0/0:41,0:41:99:0,117,1755 0/0:32,0:32:62:0,62,1119 0/0:25,0:25:66:0,66,990 0/0:60,0:60:99:0,120,1800 0/0:25,0:25:60:0,60,900 0/0:67,0:67:99:0,120,1800 0/0:47,0:47:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:31,0:31:61:0,61,1281 0/0:33,0:33:90:0,90,1350 0/0:29,0:29:63:0,63,945 0/0:40,0:40:99:0,105,1575 0/0:37,0:37:99:0,105,1575 0/0:25,0:25:63:0,63,945 0/0:29,0:29:66:0,66,990 0/0:27,0:27:81:0,81,991 0/0:27,0:27:65:0,65,990 0/0:25,0:25:63:0,63,945 0/0:43,0:43:99:0,120,1800 0/0:40,0:40:99:0,108,1620 0/0:61,0:61:99:0,120,1800 0/0:22,0:22:63:0,63,945 0/0:20,0:20:60:0,60,747 0/0:31,0:31:78:0,78,1170 0/0:58,0:58:99:0,120,1800 0/0:21,0:21:63:0,63,764 0/0:22,0:22:60:0,60,900 0/0:40,0:40:81:0,81,1215 0/0:28,0:28:75:0,75,1125 0/1:24,28:52:99:827,0,684 0/0:20,0:20:60:0,60,758 0/0:36,0:36:99:0,105,1575 0/0:31,0:31:75:0,75,1125 0/0:35,0:35:99:0,99,1485 0/0:53,0:53:99:0,120,1800 +20 17932210 rs2273448 C T 650789.00 PASS HWP=3.0E-4;AC=56;culprit=MQ;MQ0=0;ReadPosRankSum=0.497;AN=200;InbreedingCoeff=0.1273;AF=0.294;GQ_STDDEV=580.13;FS=1.194;DP=55130;GQ_MEAN=482.65;POSITIVE_TRAIN_SITE;VQSLOD=1.1;ClippingRankSum=-0.17;BaseQRankSum=-2.616;MLEAF=0.294;MLEAC=511;MQ=57.87;QD=16.3;DB;MQRankSum=-0.353;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:45,39:84:99:1148,0,1348 0/0:26,0:26:69:0,69,1003 0/1:46,41:87:99:1118,0,1334 0/0:34,0:34:78:0,78,1170 0/0:30,0:30:66:0,66,990 0/0:34,0:34:87:0,87,1305 0/1:66,43:109:99:1251,0,1864 0/0:29,0:29:62:0,62,1035 0/1:50,52:102:99:1407,0,1541 0/0:23,0:23:63:0,63,945 0/0:35,0:35:87:0,87,1305 0/0:26,0:26:60:0,60,900 0/1:52,38:90:99:1141,0,1502 1/1:0,69:69:99:2218,207,0 0/1:33,21:54:99:579,0,975 0/1:47,42:89:99:1244,0,1407 0/1:45,42:87:99:1121,0,1321 1/1:0,72:72:99:2425,216,0 0/0:26,0:26:60:0,60,900 0/0:36,0:36:81:0,81,1215 0/0:26,0:26:66:0,66,990 0/0:30,0:30:63:0,63,945 0/0:35,0:35:75:0,75,1125 0/0:30,0:30:78:0,78,1170 0/1:103,90:193:99:2219,0,2849 0/0:48,0:48:99:0,114,1710 0/0:37,0:37:93:0,93,1395 0/1:58,56:114:99:1492,0,1714 0/0:28,0:28:66:0,66,990 0/0:27,0:27:66:0,66,957 0/1:43,43:86:99:1129,0,1416 0/0:23,0:23:60:0,60,900 0/0:71,0:71:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/1:49,57:106:99:1376,0,1209 0/1:38,35:73:99:878,0,1139 0/0:33,0:33:93:0,93,1132 0/0:33,0:33:84:0,84,1260 0/1:60,56:116:99:1540,0,1850 0/0:38,0:38:79:0,79,1395 0/0:36,0:36:93:0,93,1395 0/0:45,0:45:99:0,120,1800 0/0:33,0:33:77:0,77,1215 0/0:40,0:40:99:0,108,1620 0/0:39,0:39:99:0,111,1487 0/0:47,0:47:96:0,96,1440 0/0:51,0:51:99:0,117,1755 0/1:74,50:124:99:1456,0,2508 0/0:52,0:52:99:0,120,1800 0/0:37,0:37:90:0,90,1350 0/1:62,45:107:99:1279,0,1978 0/0:30,0:30:69:0,69,1035 0/0:39,0:39:87:0,87,1305 0/0:43,0:43:99:0,99,1485 0/1:56,57:113:99:1472,0,1512 1/1:0,96:96:99:3381,289,0 0/1:59,39:98:99:1076,0,1981 0/0:56,0:56:99:0,120,1800 0/0:45,0:45:99:0,111,1665 0/1:58,47:105:99:1346,0,1836 0/1:50,31:81:99:866,0,1592 0/0:74,0:74:99:0,120,1800 0/0:39,0:39:90:0,90,1350 0/1:45,49:94:99:1439,0,1300 0/1:57,34:91:99:977,0,1648 0/1:49,49:98:99:1279,0,1549 1/1:0,63:63:99:2140,189,0 0/1:57,79:136:99:2241,0,1729 0/0:25,0:25:60:0,60,900 0/1:93,72:165:99:2111,0,2886 1/1:0,91:91:99:3113,273,0 0/1:132,93:225:99:2474,0,3950 0/1:57,39:96:99:977,0,1924 0/1:53,56:109:99:1482,0,1689 0/0:29,0:29:63:0,63,945 0/0:40,0:40:99:0,105,1575 1/1:0,89:89:99:3143,267,0 0/0:25,0:25:63:0,63,945 0/0:29,0:29:66:0,66,990 0/1:30,34:64:99:954,0,1014 0/0:27,0:27:65:0,65,990 0/0:25,0:25:63:0,63,945 0/1:71,50:121:99:1380,0,2352 0/1:65,58:123:99:1679,0,2097 0/0:61,0:61:99:0,120,1800 0/1:48,50:98:99:1334,0,1287 0/0:20,0:20:60:0,60,747 0/1:56,46:102:99:1228,0,1665 0/1:85,57:142:99:1528,0,2856 1/1:0,75:75:99:2536,225,0 0/0:22,0:22:60:0,60,900 0/0:40,0:40:81:0,81,1215 1/1:0,74:74:99:2585,222,0 1/1:0,86:86:99:2829,258,0 0/1:41,37:78:99:927,0,952 0/1:60,46:106:99:1208,0,1959 0/0:31,0:31:75:0,75,1125 0/1:39,33:72:99:904,0,1296 0/1:78,49:127:99:1248,0,2818 +20 17933368 . T TG 58616.40 PASS HWP=0.0027;AC=9;culprit=FS;MQ0=0;ReadPosRankSum=-0.119;AN=200;InbreedingCoeff=0.1233;AF=0.063;GQ_STDDEV=125.67;FS=0.531;DP=22452;GQ_MEAN=95.16;POSITIVE_TRAIN_SITE;VQSLOD=4.31;ClippingRankSum=-0.061;BaseQRankSum=0.387;MLEAF=0.063;MLEAC=110;MQ=60.09;QD=17.73;MQRankSum=0.395;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:16,0:16:23:0,23,585 0/0:18,0:18:45:0,45,675 0/0:26,0:26:69:0,69,1035 0/0:24,0:24:60:0,60,900 0/0:15,0:15:36:0,36,540 0/0:25,0:25:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:13,0:13:27:0,27,405 0/0:30,0:30:66:0,66,1170 0/0:15,0:15:36:0,36,540 0/0:23,0:23:60:0,60,900 0/0:12,0:12:30:0,30,450 0/0:26,0:26:63:0,63,945 0/0:13,0:13:24:0,24,360 0/0:21,0:21:60:0,60,900 0/0:30,0:30:75:0,75,1050 0/0:26,0:26:65:0,65,990 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:33,0:33:75:0,75,1125 0/0:25,0:25:60:0,60,900 0/0:32,0:32:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:51,0:51:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:26,0:26:63:0,63,945 0/0:26,0:26:63:0,63,945 0/0:29,0:29:68:0,68,1043 0/0:23,0:23:60:0,60,852 0/0:26,0:26:66:0,66,990 0/0:26,0:26:66:0,66,990 0/0:27,0:27:66:0,66,990 0/0:37,0:37:84:0,84,1350 0/0:39,0:39:99:0,99,1340 0/0:36,0:36:93:0,93,1395 0/0:23,0:23:60:0,60,696 0/0:24,0:24:63:0,63,945 0/0:25,0:25:64:0,64,990 0/0:29,0:29:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:14,0:14:27:0,27,405 0/1:7,8:15:99:253,0,218 0/0:14,0:14:39:0,39,556 0/0:29,0:29:72:0,72,1080 0/0:26,0:26:69:0,69,909 0/1:19,19:38:99:591,0,599 0/1:20,11:31:99:302,0,657 0/0:31,0:31:81:0,81,1035 0/0:28,0:28:63:0,63,945 0/1:26,28:54:99:880,0,805 0/1:17,13:30:99:394,0,547 0/0:25,0:25:61:0,61,945 0/0:24,0:24:60:0,60,900 0/0:28,0:28:74:0,74,1117 0/0:28,0:28:60:0,60,900 0/1:13,7:20:99:225,0,425 0/0:26,0:26:60:0,60,900 0/0:29,0:29:70:0,70,1080 0/0:29,0:29:62:0,62,1080 0/0:32,0:32:75:0,75,1125 0/0:29,0:29:66:0,66,990 0/0:25,0:25:60:0,60,1035 0/1:23,24:47:99:747,0,713 0/1:29,19:48:99:565,0,916 0/0:26,0:26:60:0,60,900 0/0:24,0:24:66:0,66,979 0/0:24,0:24:60:0,60,872 0/0:10,0:10:24:0,24,333 0/0:37,0:37:87:0,87,1305 0/0:11,0:11:33:0,33,389 0/0:29,0:29:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:20,0:20:60:0,60,731 0/1:7,9:16:99:288,0,215 0/0:21,0:21:60:0,60,900 0/0:19,0:19:0:0,0,439 0/0:8,0:8:21:0,21,315 0/0:9,0:9:21:0,21,315 0/0:23,0:23:63:0,63,945 0/0:11,0:11:30:0,30,450 0/0:22,0:22:60:0,60,900 0/0:16,0:16:33:0,33,495 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:16,0:16:42:0,42,630 0/0:36,0:36:78:0,78,1305 0/0:23,0:23:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:35,0:35:83:0,83,1260 0/0:34,0:34:87:0,87,1176 0/0:31,0:31:84:0,84,1231 0/0:26,0:26:60:0,60,900 0/0:9,0:9:24:0,24,281 0/0:26,0:26:63:0,63,945 0/0:22,0:22:60:0,60,724 0/0:12,0:12:27:0,27,405 0/0:9,0:9:21:0,21,315 0/0:15,0:15:42:0,42,630 0/0:29,0:29:69:0,69,1035 +20 17934791 . C CT 14996.20 PASS HWP=0.1027;AC=8;culprit=ReadPosRankSum;MQ0=0;ReadPosRankSum=0.63;AN=200;InbreedingCoeff=0.1358;AF=0.008046;GQ_STDDEV=109.39;FS=1.577;DP=52538;GQ_MEAN=116.46;POSITIVE_TRAIN_SITE;VQSLOD=3.68;ClippingRankSum=-0.855;BaseQRankSum=-0.414;MLEAF=0.008046;MLEAC=14;MQ=60.41;QD=15.15;MQRankSum=0.471;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:59,0:59:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:54,0:54:99:0,108,1620 0/1:39,33:72:99:953,0,1145 0/1:53,38:91:99:1099,0,1540 0/0:66,0:66:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:73,0:73:99:0,120,1800 0/1:41,44:85:99:1176,0,1214 0/1:38,41:79:99:1137,0,1117 0/0:68,0:68:99:0,120,1800 0/0:56,0:56:99:0,114,1710 0/0:42,0:42:96:0,96,1440 0/0:40,0:40:84:0,84,1260 0/0:42,0:42:96:0,96,1440 0/0:36,0:36:84:0,84,1260 0/0:53,0:53:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:40,0:40:85:0,85,1307 0/0:42,0:42:84:0,84,1260 0/0:43,0:43:96:0,96,1440 0/0:68,0:68:99:0,120,1800 0/0:67,0:67:99:0,120,1800 0/0:81,0:81:99:0,120,1800 0/0:72,0:72:99:0,120,1800 0/0:78,0:78:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:58,0:58:99:0,111,1665 0/0:46,0:46:99:0,102,1530 0/0:53,0:53:99:0,120,1800 0/0:112,0:112:99:0,120,1800 0/0:126,0:126:99:0,120,1800 0/1:65,56:121:99:1603,0,1949 0/0:46,0:46:96:0,96,1440 0/0:56,0:56:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:66,0:66:99:0,120,1800 0/0:87,0:87:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/0:84,0:84:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/1:58,45:103:99:1274,0,1751 0/0:94,0:94:99:0,120,1800 0/0:92,0:92:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:62,0:62:99:0,120,1800 0/0:50,0:50:99:0,108,1620 0/0:49,0:49:99:0,120,1800 0/0:80,0:80:99:0,120,1800 0/0:57,0:57:99:0,120,1800 0/0:100,0:100:99:0,120,1800 0/0:93,0:93:99:0,120,1800 0/0:82,0:82:99:0,120,1800 1/1:1,110:111:99:3852,295,0 0/0:65,0:65:99:0,120,1800 0/0:77,0:77:99:0,120,1800 0/0:129,0:129:99:0,120,1800 0/0:85,0:85:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:50,0:50:99:0,102,1530 0/0:37,0:37:84:0,84,1260 0/0:29,0:29:66:0,66,990 0/0:96,0:96:99:0,120,1800 0/0:39,0:39:81:0,81,1215 0/0:79,0:79:99:0,120,1800 0/0:47,0:47:99:0,105,1575 0/0:76,0:76:99:0,120,1800 0/0:42,0:42:90:0,90,1350 0/0:50,0:50:99:0,120,1800 0/0:27,0:27:66:0,66,990 0/0:51,0:51:99:0,114,1710 0/0:48,0:48:99:0,108,1620 0/0:48,0:48:99:0,102,1530 0/0:50,0:50:99:0,99,1485 0/0:30,0:30:75:0,75,1125 0/0:36,0:36:93:0,93,1395 0/0:35,0:35:67:0,67,1170 0/0:55,0:55:99:0,114,1710 0/0:54,0:54:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:56,0:56:99:0,120,1800 0/0:55,0:55:99:0,117,1755 0/0:44,0:44:93:0,93,1395 0/0:96,0:96:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:52,0:52:99:0,105,1575 0/0:43,0:43:99:0,99,1485 0/0:37,0:37:86:0,86,1350 0/0:48,0:48:99:0,102,1530 0/0:51,0:51:81:0,81,1215 0/0:33,0:33:78:0,78,1170 0/0:64,0:64:99:0,120,1800 0/0:27,0:27:66:0,66,990 0/0:44,0:44:99:0,108,1620 +20 17935977 rs41276406 A G 20527.20 PASS HWP=1.0;AC=6;culprit=MQ;MQ0=0;ReadPosRankSum=-0.212;AN=200;InbreedingCoeff=0.0056;AF=0.029;GQ_STDDEV=74.16;FS=0.0;DP=15051;GQ_MEAN=59.48;POSITIVE_TRAIN_SITE;VQSLOD=0.82;ClippingRankSum=0.212;BaseQRankSum=2.71;MLEAF=0.029;MLEAC=50;MQ=57.07;QD=17.51;DB;MQRankSum=0.708;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:20,0:20:60:0,60,803 0/0:22,0:22:54:0,54,810 0/0:11,0:11:33:0,33,406 0/1:11,15:26:99:509,0,310 0/0:13,0:13:36:0,36,540 0/0:13,0:13:36:0,36,483 0/0:21,0:21:60:0,60,825 0/0:13,0:13:39:0,39,498 0/0:20,0:20:60:0,60,778 0/1:7,10:17:99:323,0,214 0/0:15,0:15:36:0,36,540 0/0:8,0:8:21:0,21,315 0/0:10,0:10:30:0,30,383 0/0:13,0:13:30:0,30,450 0/0:22,0:22:60:0,60,862 0/0:21,0:21:60:0,60,893 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,847 0/0:20,0:20:60:0,60,708 0/0:10,0:10:21:0,21,405 0/0:28,0:28:72:0,72,1080 0/0:22,0:22:63:0,63,945 0/0:24,0:24:63:0,63,945 0/0:14,0:14:32:0,32,552 0/0:21,0:21:60:0,60,900 0/0:12,0:12:27:0,27,405 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,805 0/0:23,0:23:60:0,60,900 0/0:23,0:23:67:0,67,879 0/0:24,0:24:60:0,60,816 0/0:13,0:13:39:0,39,494 0/0:23,0:23:60:0,60,900 0/1:19,16:35:99:571,0,594 0/0:29,0:29:72:0,72,1080 0/0:10,0:10:24:0,24,403 0/0:10,0:10:30:0,30,363 0/0:22,0:22:60:0,60,900 0/0:16,0:16:36:0,36,597 0/0:23,0:23:60:0,60,900 0/0:12,0:12:25:0,25,476 0/0:9,0:9:27:0,27,338 0/0:16,0:16:42:0,42,629 0/0:22,0:22:60:0,60,800 0/0:22,0:22:60:0,60,881 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:15,20:35:99:668,0,441 0/1:29,28:57:99:993,0,918 0/0:34,0:34:78:0,78,1256 0/0:22,0:22:60:0,60,841 0/0:14,0:14:39:0,39,515 0/0:15,0:15:32:0,32,585 0/0:13,0:13:28:0,28,470 0/0:27,0:27:60:0,60,900 0/0:21,0:21:63:0,63,757 0/0:24,0:24:60:0,60,900 0/0:18,0:18:48:0,48,720 0/0:21,0:21:60:0,60,892 0/0:31,0:31:80:0,80,1159 0/0:17,0:17:48:0,48,720 0/0:12,0:12:33:0,33,482 0/0:28,0:28:72:0,72,1215 0/0:16,0:16:42:0,42,630 0/0:9,0:9:21:0,21,315 0/0:23,0:23:60:0,60,900 0/1:7,6:13:99:214,0,230 0/0:5,0:5:15:0,15,180 0/0:36,0:36:87:0,87,1305 0/0:10,0:10:30:0,30,357 0/0:23,0:23:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:20,0:20:60:0,60,740 0/0:7,0:7:21:0,21,300 0/0:7,0:7:21:0,21,254 0/0:8,0:8:21:0,21,315 0/0:21,0:21:60:0,60,824 0/0:20,0:20:60:0,60,752 0/0:11,0:11:23:0,23,393 0/0:4,0:4:12:0,12,178 0/0:13,0:13:39:0,39,477 0/0:8,0:8:24:0,24,300 0/0:11,0:11:33:0,33,416 0/0:13,0:13:39:0,39,478 0/0:20,0:20:60:0,60,757 0/0:21,0:21:60:0,60,792 0/0:9,0:9:27:0,27,341 0/0:21,0:21:54:0,54,810 0/0:24,0:24:63:0,63,945 0/0:9,0:9:27:0,27,336 0/0:21,0:21:60:0,60,900 0/0:11,0:11:30:0,30,450 0/0:14,0:14:30:0,30,553 0/0:8,0:8:24:0,24,332 0/0:7,0:7:21:0,21,277 0/0:13,0:13:35:0,35,479 0/0:7,0:7:21:0,21,260 0/0:16,0:16:48:0,48,588 0/0:15,0:15:45:0,45,539 +20 17943492 rs753213 A T 514406.00 PASS HWP=0.0;AC=56;culprit=QD;MQ0=0;ReadPosRankSum=0.112;AN=200;InbreedingCoeff=0.1549;AF=0.279;GQ_STDDEV=425.91;FS=2.557;DP=38929;GQ_MEAN=349.31;POSITIVE_TRAIN_SITE;VQSLOD=4.54;ClippingRankSum=-0.089;BaseQRankSum=-0.306;MLEAF=0.279;MLEAC=486;MQ=59.71;QD=20.39;DB;MQRankSum=0.17;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:15,22:37:99:746,0,478 0/0:29,0:29:74:0,74,1170 0/1:31,36:67:99:1003,0,882 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/1:47,20:67:99:570,0,1528 0/0:28,0:28:69:0,69,1035 0/1:31,24:55:99:715,0,962 0/0:24,0:24:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,900 0/1:33,33:66:99:1049,0,1014 1/1:0,48:48:99:1820,144,0 0/1:29,17:46:99:479,0,917 0/1:29,28:57:99:819,0,889 0/1:26,21:47:99:629,0,800 1/1:0,65:65:99:2298,195,0 0/0:28,0:28:67:0,67,1035 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:34,0:34:60:0,60,900 0/1:82,73:155:99:2291,0,2463 0/0:32,0:32:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/1:31,44:75:99:1384,0,897 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/1:31,23:54:99:665,0,934 0/0:25,0:25:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:39,0:39:96:0,96,1456 0/1:28,23:51:99:652,0,896 0/1:27,35:62:99:1052,0,854 0/0:30,0:30:63:0,63,945 0/0:25,0:25:63:0,63,945 0/1:31,38:69:99:1235,0,990 0/0:25,0:25:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:66:0,66,990 0/0:30,0:30:72:0,72,1080 0/1:49,39:88:99:1274,0,1685 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/1:18,26:44:99:826,0,499 0/0:25,0:25:60:0,60,900 0/0:41,0:41:99:0,108,1620 0/0:28,0:28:63:0,63,945 0/1:33,34:67:99:1005,0,1041 1/1:0,79:79:99:2951,238,0 0/1:24,37:61:99:1122,0,721 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/1:31,24:55:99:730,0,1037 0/1:32,35:67:99:1068,0,964 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/1:36,26:62:99:722,0,1129 0/1:29,32:61:99:983,0,910 0/1:15,14:29:99:463,0,506 1/1:0,31:31:93:1130,93,0 0/1:37,62:99:99:2056,0,1166 0/0:27,0:27:63:0,63,945 0/1:38,35:73:99:1114,0,1132 1/1:0,45:45:99:1728,135,0 0/1:35,32:67:99:975,0,1018 0/1:16,20:36:99:623,0,452 0/1:20,21:41:99:651,0,641 0/0:25,0:25:60:0,60,900 0/0:31,0:31:60:0,60,900 1/1:0,49:49:99:1803,147,0 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/1:15,14:29:99:435,0,485 0/0:24,0:24:60:0,60,900 0/0:23,0:23:60:0,60,900 0/1:26,28:54:99:894,0,774 0/1:23,20:43:99:624,0,749 0/0:22,0:22:60:0,60,900 0/1:29,32:61:99:992,0,872 0/0:32,0:32:69:0,69,1035 0/1:26,28:54:99:905,0,787 0/1:58,49:107:99:1500,0,1804 1/1:0,82:82:99:3089,247,0 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,990 1/1:0,42:42:99:1566,126,0 1/1:0,70:70:99:2462,210,0 0/1:25,26:51:99:744,0,793 0/1:14,14:28:99:424,0,443 0/0:24,0:24:60:0,60,900 0/1:23,17:40:99:510,0,750 0/1:21,21:42:99:620,0,706 +20 17943534 rs139929147 GGAA G 1182.31 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=-0.708;AN=200;InbreedingCoeff=-0.0012;AF=0.001149;GQ_STDDEV=28.62;FS=3.628;DP=24115;GQ_MEAN=65.16;VQSLOD=2.6;ClippingRankSum=-1.073;BaseQRankSum=2.59;MLEAF=0.001149;MLEAC=2;MQ=58.32;QD=15.35;DB;MQRankSum=0.142;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:26,0:26:60:0,60,900 0/0:29,0:29:74:0,74,1170 0/0:28,0:28:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:28,0:28:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:27,0:27:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:29,0:29:70:0,70,1125 0/0:28,0:28:67:0,67,1035 0/0:26,0:26:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:34,0:34:60:0,60,900 0/0:48,0:48:96:0,96,1440 0/0:32,0:32:72:0,72,1080 0/0:26,0:26:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:63:0,63,945 0/0:26,0:26:63:0,63,893 0/0:25,0:25:63:0,63,945 0/0:27,0:27:66:0,66,990 0/0:30,0:30:60:0,60,900 0/0:39,0:39:96:0,96,1456 0/0:31,0:31:63:0,63,945 0/0:31,0:31:69:0,69,1035 0/0:30,0:30:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:28,0:28:66:0,66,990 0/0:25,0:25:60:0,60,900 0/0:24,0:24:66:0,66,990 0/0:26,0:26:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:69:0,69,1035 0/0:29,0:29:69:0,69,1035 0/0:31,0:31:66:0,66,990 0/0:30,0:30:72:0,72,1080 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:28,0:28:63:0,63,945 0/0:27,0:27:63:0,63,945 0/0:33,0:33:71:0,71,1215 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:34,0:34:69:0,69,1035 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:23,0:23:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:26,0:26:63:0,63,945 0/1:26,16:42:99:593,0,1200 0/0:30,0:30:60:0,60,900 0/0:30,0:30:63:0,63,945 0/0:25,0:25:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:7,0:7:21:0,21,268 0/0:31,0:31:60:0,60,900 0/0:26,0:26:57:0,57,855 0/0:24,0:24:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:13,0:13:27:0,27,405 0/0:10,0:10:27:0,27,405 0/0:25,0:25:60:0,60,900 0/0:32,0:32:62:0,62,1228 0/0:22,0:22:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:32,0:32:69:0,69,1035 0/0:25,0:25:60:0,60,900 0/0:32,0:32:63:0,63,945 0/0:25,0:25:63:0,63,945 0/0:26,0:26:60:0,60,900 0/0:26,0:26:60:0,60,990 0/0:23,0:23:63:0,63,945 0/0:31,0:31:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:28,0:28:63:0,63,945 0/0:24,0:24:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:23,0:23:60:0,60,900 +20 17948894 rs6111762 G A 607.19 PASS HWP=0.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=1.23;AN=18;InbreedingCoeff=0.2346;AF=0.082;GQ_STDDEV=6.73;FS=0.0;DP=235;GQ_MEAN=6.03;POSITIVE_TRAIN_SITE;VQSLOD=3.78;ClippingRankSum=-1.231;BaseQRankSum=-1.231;MLEAF=0.082;MLEAC=13;MQ=60.0;QD=25.3;DB;MQRankSum=1.23;CCC=158;NCC=791 GT:AD:DP:GQ:PL ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:1,0:1:3:0,3,33 0/0:2,0:2:6:0,6,52 0/0:2,0:2:6:0,6,68 0/0:2,0:2:6:0,6,60 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,66 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 1/1:0,5:5:15:162,15,0 0/0:2,0:2:6:0,6,69 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:1,0:1:.:. ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,57 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:2,0:2:.:. ./.:1,0:1:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,73 ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. ./.:0,0:0:.:. +20 17950545 rs11551768 A T 164066.00 PASS HWP=0.022;AC=31;culprit=FS;MQ0=0;ReadPosRankSum=0.705;AN=200;InbreedingCoeff=0.0899;AF=0.088;GQ_STDDEV=365.94;FS=0.0;DP=39327;GQ_MEAN=218.73;POSITIVE_TRAIN_SITE;VQSLOD=5.62;ClippingRankSum=-0.36;BaseQRankSum=-1.802;MLEAF=0.088;MLEAC=153;MQ=59.7;QD=14.84;DB;MQRankSum=0.218;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:40,31:71:99:873,0,1165 0/1:33,29:62:99:811,0,948 0/0:33,0:33:75:0,75,1125 0/1:34,31:65:99:972,0,950 0/1:48,45:93:99:1340,0,1402 1/1:2,85:87:99:2849,255,0 0/1:48,57:105:99:1605,0,1448 0/1:42,20:62:99:511,0,1383 0/0:41,0:41:99:0,99,1485 0/1:38,38:76:99:1167,0,1131 0/1:33,40:73:99:1088,0,981 1/1:1,57:58:99:1982,171,0 0/0:40,0:40:96:0,96,1440 0/0:30,0:30:62:0,62,1051 0/0:33,0:33:72:0,72,1080 0/0:46,0:46:99:0,105,1575 0/0:29,0:29:66:0,66,990 0/0:37,0:37:93:0,93,1395 0/1:44,41:85:99:1025,0,1349 0/0:50,0:50:99:0,111,1665 0/0:40,0:40:82:0,82,1360 0/0:36,0:36:87:0,87,1146 0/0:33,0:33:75:0,75,1125 0/1:62,74:136:99:1877,0,1935 0/1:63,59:122:99:1639,0,1861 0/0:52,0:52:99:0,120,1800 0/1:47,47:94:99:1302,0,1303 0/1:46,38:84:99:1025,0,1417 0/0:35,0:35:87:0,87,1288 0/1:38,35:73:99:969,0,1102 0/0:35,0:35:85:0,85,1445 0/0:33,0:33:72:0,72,1080 0/0:90,0:90:99:0,120,1800 0/1:94,83:177:99:2277,0,2857 0/1:64,63:127:99:1639,0,1909 0/0:28,0:28:60:0,60,900 0/0:36,0:36:87:0,87,1305 0/1:61,43:104:99:1180,0,1815 0/1:34,26:60:99:714,0,1078 0/0:61,0:61:99:0,120,1800 0/0:37,0:37:95:0,95,1322 0/1:53,30:83:99:785,0,1634 0/0:52,0:52:99:0,120,1800 0/1:33,56:89:99:1585,0,933 0/0:49,0:49:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:45,0:45:99:0,111,1662 0/1:52,54:106:99:1488,0,1548 0/0:52,0:52:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:43,0:43:98:0,98,1708 0/0:48,0:48:99:0,111,1665 0/0:40,0:40:99:0,99,1415 0/0:30,0:30:78:0,78,1170 0/0:83,0:83:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:54,0:54:99:0,120,1800 1/1:1,111:112:99:3869,299,0 0/1:50,58:108:99:1642,0,1345 0/0:50,0:50:99:0,120,1800 0/1:84,48:132:99:1218,0,2722 0/0:48,0:48:99:0,120,1800 0/0:43,0:43:99:0,120,1800 0/0:40,0:40:99:0,108,1620 0/0:27,0:27:72:0,72,1080 0/0:28,0:28:72:0,72,938 0/0:56,0:56:99:0,120,1800 0/0:36,0:36:78:0,78,1170 0/0:55,0:55:99:0,120,1800 0/0:37,0:37:96:0,96,1475 0/0:53,0:53:99:0,120,1800 0/0:40,0:40:98:0,98,1665 0/0:40,0:40:93:0,93,1459 0/0:33,0:33:70:0,70,1308 0/0:34,0:34:87:0,87,1255 0/0:36,0:36:96:0,96,1440 0/0:26,0:26:60:0,60,900 0/1:56,40:96:99:1023,0,1687 0/0:22,0:22:63:0,63,945 0/1:25,26:51:99:732,0,801 0/0:28,0:28:84:0,84,1039 0/0:48,0:48:99:0,114,1710 0/0:47,0:47:99:0,99,1485 0/0:51,0:51:99:0,120,1800 0/0:36,0:36:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:42,0:42:99:0,108,1620 0/0:56,0:56:99:0,120,1800 0/0:31,0:31:69:0,69,1035 0/0:28,0:28:78:0,78,947 0/0:32,0:32:87:0,87,1305 0/0:28,0:28:68:0,68,1170 0/0:42,0:42:99:0,102,1530 0/0:27,0:27:69:0,69,1035 0/0:39,0:39:99:0,105,1575 0/0:43,0:43:99:0,108,1620 0/0:28,0:28:66:0,66,990 0/0:39,0:39:99:0,103,1665 +20 17950772 rs73107120 A G 8777.05 PASS HWP=1.0;AC=2;culprit=FS;MQ0=0;ReadPosRankSum=1.2;AN=200;InbreedingCoeff=-0.0046;AF=0.004598;GQ_STDDEV=99.26;FS=0.0;DP=35567;GQ_MEAN=96.55;POSITIVE_TRAIN_SITE;VQSLOD=4.1;ClippingRankSum=-0.228;BaseQRankSum=3.86;MLEAF=0.004598;MLEAC=8;MQ=59.58;QD=13.36;DB;MQRankSum=1.44;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:48,0:48:99:0,117,1755 0/0:43,0:43:90:0,90,1350 0/0:33,0:33:75:0,75,1125 0/0:46,0:46:99:0,115,1582 0/0:38,0:38:90:0,90,1350 0/0:48,0:48:99:0,117,1755 0/0:51,0:51:99:0,120,1800 0/0:32,0:32:69:0,69,1035 0/0:41,0:41:99:0,99,1485 0/0:38,0:38:93:0,93,1395 0/0:42,0:42:99:0,99,1485 0/0:35,0:35:90:0,90,1350 0/0:40,0:40:96:0,96,1440 0/0:30,0:30:62:0,62,1051 0/0:33,0:33:72:0,72,1080 0/0:46,0:46:99:0,105,1575 0/0:29,0:29:66:0,66,990 0/0:37,0:37:93:0,93,1395 0/0:29,0:29:72:0,72,1080 0/0:50,0:50:99:0,111,1665 0/0:40,0:40:82:0,82,1360 0/0:36,0:36:87:0,87,1146 0/0:33,0:33:75:0,75,1125 0/0:44,0:44:81:0,81,1215 0/1:132,57:189:99:1501,0,3791 0/0:52,0:52:99:0,120,1800 0/0:76,0:76:99:0,120,1800 0/1:47,51:98:99:1659,0,1512 0/0:35,0:35:87:0,87,1288 0/0:40,0:40:96:0,96,1440 0/0:35,0:35:85:0,85,1445 0/0:33,0:33:72:0,72,1080 0/0:90,0:90:99:0,120,1800 0/0:122,0:122:99:0,120,1800 0/0:94,0:94:99:0,120,1800 0/0:28,0:28:60:0,60,900 0/0:36,0:36:87:0,87,1305 0/0:43,0:43:99:0,108,1620 0/0:57,0:57:99:0,120,1800 0/0:61,0:61:99:0,120,1800 0/0:37,0:37:95:0,95,1322 0/0:65,0:65:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:64,0:64:99:0,120,1800 0/0:45,0:45:99:0,111,1662 0/0:94,0:94:99:0,120,1800 0/0:52,0:52:99:0,120,1800 0/0:51,0:51:99:0,120,1800 0/0:43,0:43:98:0,98,1708 0/0:48,0:48:99:0,111,1665 0/0:40,0:40:99:0,99,1415 0/0:30,0:30:78:0,78,1170 0/0:83,0:83:99:0,120,1800 0/0:53,0:53:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:65,0:65:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:71,0:71:99:0,120,1800 0/0:50,0:50:99:0,120,1800 0/0:122,0:122:99:0,120,1800 0/0:48,0:48:99:0,120,1800 0/0:43,0:43:99:0,120,1800 0/0:40,0:40:99:0,108,1620 0/0:27,0:27:72:0,72,1080 0/0:28,0:28:72:0,72,938 0/0:56,0:56:99:0,120,1800 0/0:36,0:36:78:0,78,1170 0/0:55,0:55:99:0,120,1800 0/0:37,0:37:96:0,96,1475 0/0:53,0:53:99:0,120,1800 0/0:40,0:40:98:0,98,1665 0/0:40,0:40:93:0,93,1459 0/0:33,0:33:70:0,70,1308 0/0:34,0:34:87:0,87,1255 0/0:36,0:36:96:0,96,1440 0/0:26,0:26:60:0,60,900 0/0:43,0:43:99:0,105,1575 0/0:22,0:22:63:0,63,945 0/0:41,0:41:92:0,92,1440 0/0:28,0:28:84:0,84,1039 0/0:48,0:48:99:0,114,1710 0/0:47,0:47:99:0,99,1485 0/0:51,0:51:99:0,120,1800 0/0:36,0:36:72:0,72,1080 0/0:30,0:30:60:0,60,900 0/0:42,0:42:99:0,108,1620 0/0:56,0:56:99:0,120,1800 0/0:31,0:31:69:0,69,1035 0/0:28,0:28:78:0,78,947 0/0:32,0:32:87:0,87,1305 0/0:28,0:28:68:0,68,1170 0/0:42,0:42:99:0,102,1530 0/0:27,0:27:69:0,69,1035 0/0:39,0:39:99:0,105,1575 0/0:43,0:43:99:0,108,1620 0/0:28,0:28:66:0,66,990 0/0:39,0:39:99:0,103,1665 +20 17956347 rs143417446 C T 1229.69 PASS HWP=1.0;AC=2;culprit=MQ;MQ0=0;ReadPosRankSum=0.478;AN=200;InbreedingCoeff=-0.0018;AF=0.001724;GQ_STDDEV=24.76;FS=0.0;DP=21184;GQ_MEAN=63.95;POSITIVE_TRAIN_SITE;VQSLOD=5.31;ClippingRankSum=0.884;BaseQRankSum=-1.205;MLEAF=0.001724;MLEAC=3;MQ=60.0;QD=11.6;DB;MQRankSum=0.884;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:22,0:22:60:0,60,900 0/0:25,0:25:60:0,60,900 0/0:31,0:31:66:0,66,990 0/0:23,0:23:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:20,0:20:60:0,60,673 0/0:28,0:28:72:0,72,1080 0/0:21,0:21:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:30,0:30:66:0,66,1125 0/0:26,0:26:66:0,66,990 0/0:21,0:21:60:0,60,759 0/0:20,0:20:60:0,60,790 0/0:24,0:24:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:25,0:25:63:0,63,945 0/0:27,0:27:60:0,60,900 0/0:27,0:27:66:0,66,990 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:28,0:28:60:0,60,900 0/0:29,0:29:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:20,0:20:60:0,60,735 0/0:38,0:38:99:0,99,1485 0/0:45,0:45:97:0,97,1620 0/0:38,0:38:82:0,82,1260 0/0:21,0:21:60:0,60,741 0/0:22,0:22:60:0,60,900 0/0:30,0:30:72:0,72,1080 0/0:25,0:25:60:0,60,900 0/0:27,0:27:60:0,60,900 0/0:26,0:26:63:0,63,945 0/0:22,0:22:60:0,60,900 0/0:26,0:26:60:0,60,900 0/0:24,0:24:62:0,62,887 0/0:25,0:25:66:0,66,990 0/0:26,0:26:72:0,72,1080 0/0:27,0:27:69:0,69,988 0/0:34,0:34:69:0,69,1035 0/0:23,0:23:60:0,60,900 0/0:33,0:33:75:0,75,1125 0/0:25,0:25:66:0,66,990 0/0:27,0:27:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:34,0:34:75:0,75,1125 0/0:25,0:25:60:0,60,900 0/0:36,0:36:95:0,95,1440 0/0:27,0:27:66:0,66,990 0/0:24,0:24:72:0,72,909 0/0:33,0:33:81:0,81,1215 0/1:21,27:48:99:768,0,593 0/0:28,0:28:69:0,69,1073 0/0:38,0:38:99:0,99,1485 0/0:25,0:25:60:0,60,900 0/1:26,17:43:99:397,0,761 0/0:22,0:22:63:0,63,945 0/0:23,0:23:66:0,66,946 0/0:20,0:20:60:0,60,773 0/0:29,0:29:78:0,78,1170 0/0:23,0:23:60:0,60,843 0/0:25,0:25:60:0,60,900 0/0:20,0:20:60:0,60,821 0/0:21,0:21:60:0,60,900 0/0:24,0:24:60:0,60,900 0/0:20,0:20:60:0,60,727 0/0:24,0:24:66:0,66,990 0/0:25,0:25:63:0,63,945 0/0:22,0:22:60:0,60,833 0/0:21,0:21:60:0,60,900 0/0:21,0:21:60:0,60,900 0/0:22,0:22:60:0,60,857 0/0:22,0:22:60:0,60,884 0/0:24,0:24:60:0,60,900 0/0:21,0:21:60:0,60,765 0/0:25,0:25:60:0,60,900 0/0:27,0:27:72:0,72,1080 0/0:23,0:23:63:0,63,945 0/0:23,0:23:63:0,63,899 0/0:20,0:20:60:0,60,757 0/0:42,0:42:99:0,102,1530 0/0:20,0:20:60:0,60,629 0/0:24,0:24:60:0,60,900 0/0:23,0:23:63:0,63,945 0/0:21,0:21:60:0,60,851 0/0:23,0:23:60:0,60,900 0/0:23,0:23:60:0,60,900 0/0:22,0:22:60:0,60,858 0/0:27,0:27:60:0,60,900 0/0:22,0:22:60:0,60,900 0/0:24,0:24:60:0,60,900 +20 17968871 rs76599088 C T 6888.33 PASS HWP=1.0;AC=1;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.175;AN=200;InbreedingCoeff=-0.0035;AF=0.003448;GQ_STDDEV=102.34;FS=5.026;DP=35657;GQ_MEAN=96.97;POSITIVE_TRAIN_SITE;VQSLOD=3.78;ClippingRankSum=0.604;BaseQRankSum=-4.397;MLEAF=0.003448;MLEAC=6;MQ=59.68;QD=12.97;DB;MQRankSum=0.715;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/0:47,0:47:99:0,120,1800 0/0:30,0:30:81:0,81,1215 0/0:22,0:22:66:0,66,797 0/0:31,0:31:81:0,81,1215 0/0:35,0:35:84:0,84,1260 0/0:23,0:23:63:0,63,945 0/0:30,0:30:81:0,81,1215 0/0:24,0:24:69:0,69,1035 0/0:36,0:36:90:0,90,1350 0/0:32,0:32:87:0,87,1305 0/0:31,0:31:78:0,78,1170 0/0:25,0:25:66:0,66,990 0/0:33,0:33:90:0,90,1350 0/0:25,0:25:66:0,66,990 0/0:33,0:33:78:0,78,1170 0/0:48,0:48:99:0,120,1800 0/0:32,0:32:84:0,84,1260 0/0:48,0:48:99:0,104,1580 0/0:38,0:38:96:0,96,1440 0/0:38,0:38:99:0,108,1620 0/0:41,0:41:75:0,75,1125 0/0:51,0:51:99:0,114,1710 0/0:46,0:46:99:0,111,1665 0/0:66,0:66:99:0,120,1800 0/0:82,0:82:99:0,120,1800 0/0:37,0:37:80:0,80,1485 0/0:54,0:54:99:0,120,1800 0/0:49,0:49:99:0,120,1800 0/0:44,0:44:99:0,99,1485 0/0:44,0:44:81:0,81,1215 0/0:34,0:34:99:0,99,1485 0/0:32,0:32:72:0,72,1080 0/0:80,0:80:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/0:39,0:39:84:0,84,1259 0/0:20,0:20:60:0,60,670 0/0:50,0:50:99:0,105,1575 0/0:43,0:43:84:0,84,1260 0/0:63,0:63:99:0,120,1800 0/0:36,0:36:72:0,72,1080 0/0:37,0:37:75:0,75,1125 0/0:27,0:27:69:0,69,1035 0/0:55,0:55:99:0,117,1755 0/0:53,0:53:99:0,111,1665 0/1:51,53:104:99:1523,0,1617 0/0:46,0:46:99:0,99,1485 0/0:77,0:77:99:0,120,1800 0/0:75,0:75:99:0,120,1800 0/0:68,0:68:99:0,120,1800 0/0:47,0:47:99:0,102,1530 0/0:47,0:47:99:0,111,1637 0/0:34,0:34:75:0,75,1125 0/0:38,0:38:78:0,78,1170 0/0:59,0:59:99:0,120,1800 0/0:54,0:54:99:0,120,1800 0/0:63,0:63:99:0,120,1800 0/0:69,0:69:99:0,120,1800 0/0:60,0:60:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/0:46,0:46:99:0,120,1800 0/0:41,0:41:99:0,108,1620 0/0:86,0:86:99:0,120,1800 0/0:52,0:52:99:0,114,1710 0/0:43,0:43:99:0,120,1800 0/0:50,0:50:99:0,111,1688 0/0:25,0:25:72:0,72,1080 0/0:32,0:32:73:0,73,1164 0/0:95,0:95:99:0,120,1800 0/0:36,0:36:81:0,81,1215 0/0:75,0:75:99:0,120,1800 0/0:34,0:34:93:0,93,1395 0/0:67,0:67:99:0,120,1800 0/0:44,0:44:99:0,120,1800 0/0:38,0:38:99:0,99,1485 0/0:31,0:31:75:0,75,1125 0/0:43,0:43:99:0,99,1485 0/0:39,0:39:99:0,102,1530 0/0:34,0:34:78:0,78,1170 0/0:52,0:52:99:0,117,1755 0/0:30,0:30:76:0,76,994 0/0:32,0:32:87:0,87,1305 0/0:30,0:30:69:0,69,1035 0/0:56,0:56:99:0,120,1800 0/0:42,0:42:92:0,92,1424 0/0:69,0:69:99:0,120,1800 0/0:33,0:33:80:0,80,1173 0/0:29,0:29:78:0,78,1170 0/0:41,0:41:99:0,105,1575 0/0:88,0:88:99:0,120,1800 0/0:31,0:31:90:0,90,1350 0/0:24,0:24:69:0,69,859 0/0:56,0:56:99:0,120,1800 0/0:37,0:37:99:0,99,1530 0/0:30,0:30:90:0,90,1022 0/0:23,0:23:63:0,63,945 0/0:35,0:35:90:0,90,1350 0/0:32,0:32:87:0,87,1305 0/0:33,0:33:90:0,90,1350 0/0:61,0:61:99:0,120,1800 +20 17968923 rs28455091 T C 600727.00 PASS HWP=0.0027;AC=55;culprit=FS;MQ0=0;ReadPosRankSum=0.24;AN=200;InbreedingCoeff=0.1048;AF=0.306;GQ_STDDEV=512.29;FS=0.525;DP=52734;GQ_MEAN=442.06;POSITIVE_TRAIN_SITE;VQSLOD=4.55;ClippingRankSum=-0.129;BaseQRankSum=2.98;MLEAF=0.306;MLEAC=533;MQ=59.27;QD=17.33;DB;MQRankSum=0.411;CCC=1740;NCC=0 GT:AD:DP:GQ:PL 0/1:37,38:75:99:1045,0,1008 0/0:30,0:30:81:0,81,1215 0/1:27,32:59:99:907,0,774 0/0:31,0:31:81:0,81,1215 0/0:35,0:35:84:0,84,1260 0/0:23,0:23:63:0,63,945 0/1:54,27:81:99:597,0,1558 0/0:24,0:24:69:0,69,1035 0/1:43,31:74:99:1068,0,1247 0/0:32,0:32:87:0,87,1305 0/0:31,0:31:78:0,78,1170 0/0:25,0:25:66:0,66,990 0/1:51,26:77:99:746,0,1359 1/1:0,46:46:99:1636,138,0 0/1:25,19:44:99:545,0,731 0/1:51,32:83:99:906,0,1520 0/1:65,37:102:99:991,0,1839 1/1:0,85:85:99:2880,255,0 0/0:38,0:38:96:0,96,1440 0/0:38,0:38:99:0,108,1620 0/0:41,0:41:75:0,75,1125 0/0:51,0:51:99:0,114,1710 0/0:46,0:46:99:0,111,1665 0/0:66,0:66:99:0,120,1800 0/1:128,107:235:99:2877,0,3190 0/0:37,0:37:80:0,80,1485 0/0:54,0:54:99:0,120,1800 0/1:48,39:87:99:1056,0,1400 0/0:44,0:44:99:0,99,1485 0/0:44,0:44:81:0,81,1215 0/1:27,32:59:99:1071,0,677 0/0:32,0:32:72:0,72,1080 0/0:80,0:80:99:0,120,1800 0/0:105,0:105:99:0,120,1800 0/0:74,0:74:99:0,120,1800 0/1:37,48:85:99:1272,0,891 0/1:46,30:76:99:776,0,1189 0/0:50,0:50:99:0,105,1575 0/0:43,0:43:84:0,84,1260 0/1:58,36:94:99:1065,0,1581 0/0:36,0:36:72:0,72,1080 0/0:37,0:37:75:0,75,1125 0/0:27,0:27:69:0,69,1035 0/0:55,0:55:99:0,117,1755 0/0:53,0:53:99:0,111,1665 0/0:49,0:49:96:0,96,1440 0/0:46,0:46:99:0,99,1485 0/0:77,0:77:99:0,120,1800 0/1:59,58:117:99:1783,0,1624 0/0:68,0:68:99:0,120,1800 0/0:47,0:47:99:0,102,1530 0/1:44,32:76:99:928,0,1292 0/0:34,0:34:75:0,75,1125 0/0:38,0:38:78:0,78,1170 0/0:59,0:59:99:0,120,1800 0/1:37,35:72:99:1103,0,1029 1/1:0,84:84:99:3192,253,0 0/1:56,40:96:99:1225,0,1613 0/0:60,0:60:99:0,120,1800 0/0:70,0:70:99:0,120,1800 0/1:39,30:69:99:912,0,1143 0/1:69,29:98:99:719,0,2026 0/0:86,0:86:99:0,120,1800 0/0:52,0:52:99:0,114,1710 0/1:39,35:74:99:1098,0,1198 0/1:57,50:107:99:1393,0,1627 0/1:35,26:61:99:758,0,1006 1/1:1,40:41:99:1403,113,0 0/1:70,49:119:99:1599,0,1993 0/0:36,0:36:81:0,81,1215 0/1:49,58:107:99:1637,0,1359 1/1:1,58:59:99:2185,167,0 0/1:98,71:169:99:2116,0,2412 0/1:40,31:71:99:1080,0,1024 0/1:38,32:70:99:1045,0,1155 0/0:31,0:31:75:0,75,1125 0/0:43,0:43:99:0,99,1485 0/1:53,50:103:99:1504,0,1314 0/0:34,0:34:78:0,78,1170 0/0:52,0:52:99:0,117,1755 0/1:26,28:54:99:938,0,710 0/0:32,0:32:87:0,87,1305 0/0:30,0:30:69:0,69,1035 0/1:42,55:97:99:1795,0,1109 0/1:37,32:69:99:1014,0,1038 0/0:69,0:69:99:0,120,1800 0/1:64,38:102:99:1030,0,1605 0/0:29,0:29:78:0,78,1170 0/1:59,36:95:99:1045,0,1729 0/1:90,64:154:99:2038,0,2412 1/1:1,105:106:99:3431,315,0 0/0:24,0:24:69:0,69,859 0/0:56,0:56:99:0,120,1800 1/1:1,63:64:99:2287,156,0 1/1:2,72:74:99:2370,172,0 0/1:48,36:84:99:892,0,1155 0/1:46,27:73:99:744,0,1225 0/0:32,0:32:87:0,87,1305 0/1:24,29:53:99:947,0,659 0/1:58,26:84:99:737,0,1676 +20 17970876 rs11908007 G T 3774.07 PASS HWP=1.0E-4;AC=2;culprit=InbreedingCoeff;MQ0=0;ReadPosRankSum=0.406;AN=182;InbreedingCoeff=-0.0132;AF=0.019;GQ_STDDEV=18.19;FS=2.936;DP=4525;GQ_MEAN=14.6;POSITIVE_TRAIN_SITE;VQSLOD=3.95;ClippingRankSum=0.358;BaseQRankSum=-0.358;MLEAF=0.022;MLEAC=34;MQ=60.0;QD=16.55;DB;MQRankSum=0.358;CCC=1564;NCC=88 GT:AD:DP:GQ:PL 0/0:3,0:3:6:0,6,90 0/0:3,0:3:6:0,6,90 0/0:6,0:6:8:0,8,135 0/0:4,0:4:9:0,9,135 ./.:1,0:1:.:. 0/0:7,0:7:6:0,6,90 0/0:6,0:6:12:0,12,180 0/0:9,0:9:9:0,9,135 0/0:6,0:6:12:0,12,180 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. 0/0:8,0:8:21:0,21,290 0/0:7,0:7:9:0,9,135 0/0:5,0:5:9:0,9,135 0/0:18,0:18:42:0,42,630 0/0:5,0:5:9:0,9,135 0/0:4,0:4:9:0,9,135 0/0:7,0:7:15:0,15,225 0/0:10,0:10:0:0,0,311 0/0:5,0:5:9:0,9,135 0/1:2,3:5:64:95,0,64 0/0:10,0:10:18:0,18,270 0/0:8,0:8:12:0,12,180 ./.:0,0:0:.:. 0/0:3,0:3:9:0,9,97 0/1:5,4:9:99:129,0,170 0/0:4,0:4:9:0,9,135 0/0:7,0:7:15:0,15,225 0/0:1,0:1:3:0,3,35 0/0:5,0:5:8:0,8,135 0/0:3,0:3:6:0,6,90 0/0:3,0:3:3:0,3,45 0/0:11,0:11:24:0,24,360 0/0:11,0:11:21:0,21,315 0/0:14,0:14:30:0,30,450 0/0:2,0:2:6:0,6,72 0/0:2,0:2:3:0,3,45 0/0:11,0:11:21:0,21,315 0/0:6,0:6:12:0,12,180 0/0:15,0:15:36:0,36,540 0/0:7,0:7:15:0,15,225 0/0:9,0:9:21:0,21,315 0/0:16,0:16:32:0,32,495 0/0:13,0:13:33:0,33,495 0/0:17,0:17:39:0,39,585 0/0:14,0:14:36:0,36,540 0/0:9,0:9:18:0,18,270 0/0:15,0:15:30:0,30,450 0/0:8,0:8:21:0,21,315 0/0:8,0:8:15:0,15,225 0/0:15,0:15:36:0,36,540 0/0:4,0:4:9:0,9,135 0/0:1,0:1:3:0,3,38 0/0:4,0:4:6:0,6,90 0/0:6,0:6:18:0,18,222 0/0:11,0:11:30:0,30,415 0/0:7,0:7:18:0,18,270 0/0:14,0:14:36:0,36,540 0/0:16,0:16:27:0,27,405 0/0:12,0:12:27:0,27,405 0/0:13,0:13:30:0,30,435 0/0:13,0:13:33:0,33,495 0/0:7,0:7:21:0,21,250 0/0:11,0:11:21:0,21,315 0/0:14,0:14:31:0,31,485 0/0:3,0:3:9:0,9,115 ./.:0,0:0:.:. ./.:1,0:1:.:. 0/0:9,0:9:21:0,21,315 0/0:3,0:3:6:0,6,90 0/0:6,0:6:12:0,12,180 0/0:3,0:3:6:0,6,90 0/0:11,0:11:30:0,30,450 0/0:2,0:2:6:0,6,73 0/0:3,0:3:6:0,6,90 ./.:0,0:0:.:. 0/0:3,0:3:3:0,3,45 0/0:2,0:2:3:0,3,45 0/0:4,0:4:6:0,6,90 ./.:0,0:0:.:. 0/0:4,0:4:3:0,3,45 0/0:5,0:5:12:0,12,180 0/0:4,0:4:9:0,9,135 0/0:2,0:2:6:0,6,68 0/0:3,0:3:6:0,6,90 0/0:4,0:4:9:0,9,135 0/0:2,0:2:3:0,3,45 0/0:3,0:3:3:0,3,45 0/0:7,0:7:18:0,18,270 0/0:12,0:12:21:0,21,315 0/0:4,0:4:9:0,9,135 ./.:1,0:1:.:. 0/0:4,0:4:9:0,9,135 0/0:3,0:3:9:0,9,103 ./.:0,0:0:.:. 0/0:2,0:2:6:0,6,75 0/0:6,0:6:15:0,15,214 0/0:8,0:8:15:0,15,225 0/0:4,0:4:6:0,6,90 0/0:3,0:3:9:0,9,108 diff --git a/hail/python/hail/methods/impex.py b/hail/python/hail/methods/impex.py index 9dc23f031e3..532b8e4ff23 100644 --- a/hail/python/hail/methods/impex.py +++ b/hail/python/hail/methods/impex.py @@ -2673,12 +2673,27 @@ def import_vcf(path, >>> ds = hl.import_vcf('data/example2.vcf.bgz', reference_genome='GRCh37') + Import a variant-partitioned dataset stored in one or more VCF files. The ``*`` is a glob + pattern which matches any string of characters. + + >>> ds = hl.import_vcf('data/samplepart*.vcf') + + Import a VCF dataset and override every header with the header from ``data/samplepart1.vcf``. If + the other VCF files are missing headers, have differing sample names, or otherwise have + incompatible headers, `header_file` can be used to enforce a consistent header. + + >>> ds = hl.import_vcf('data/samplepart*.vcf', header_file='data/samplepart1.vcf') + Import a VCF with GRCh38 as the reference genome that incorrectly uses the contig names from GRCh37 (i.e. uses contig name "1" instead of "chr1"). >>> recode = {f"{i}":f"chr{i}" for i in (list(range(1, 23)) + ['X', 'Y'])} >>> ds = hl.import_vcf('data/grch38_bad_contig_names.vcf', reference_genome='GRCh38', contig_recoding=recode) + Import a bgzipped VCF which uses the "gz" extension rather than the "bgz" extension: + + >>> ds = hl.import_vcf('data/samplepart*.vcf.gz', force_bgz=True) + Notes ----- @@ -2694,11 +2709,14 @@ def import_vcf(path, either be uncompressed (**.vcf**) or block compressed (**.vcf.bgz**). If you have a large compressed VCF that ends in **.vcf.gz**, it is likely that the file is actually block-compressed, and you should rename the file to - **.vcf.bgz** accordingly. If you actually have a standard gzipped file, it - is possible to import it to Hail using the `force` parameter. However, this - is not recommended -- all parsing will have to take place on one node - because gzip decompression is not parallelizable. In this case, import will - take significantly longer. + **.vcf.bgz** accordingly. If you are unable to rename this file, please use + `force_bgz=True` to ignore the extension and treat this file as + block-gzipped. + + If you have a **non-block** (aka standard) gzipped file, you may use + `force=True`; however, we strongly discourage this because each file will be + processed by a single core. Import will take significantly longer for any + non-trivial dataset. :func:`.import_vcf` does not perform deduplication - if the provided VCF(s) contain multiple records with the same chrom, pos, ref, alt, all these @@ -2754,16 +2772,17 @@ def import_vcf(path, Parameters ---------- path : :class:`str` or :obj:`list` of :obj:`str` - VCF file(s) to read. + One or more paths to VCF files to read. Each path may or may not include glob expressions + like ``*``, ``?``, or ``[abc123]``. force : :obj:`bool` If ``True``, load **.vcf.gz** files serially. No downstream operations can be parallelized, so this mode is strongly discouraged. force_bgz : :obj:`bool` - If ``True``, load **.vcf.gz** files as blocked gzip files, assuming - that they were actually compressed using the BGZ codec. + If ``True``, load **.vcf.gz** files as blocked gzip files, assuming that they were actually + compressed using the BGZ codec. header_file : :class:`str`, optional Optional header override file. If not specified, the first file in - `path` is used. + `path` is used. Glob patterns are not allowed in the `header_file`. min_partitions : :obj:`int`, optional Minimum partitions to load per file. drop_samples : :obj:`bool` @@ -2807,6 +2826,7 @@ def import_vcf(path, Returns ------- :class:`.MatrixTable` + """ if force: hl.utils.warning( From eeb31689255cf6910af36d59b908b6ea9ad8f4c7 Mon Sep 17 00:00:00 2001 From: Dan King Date: Mon, 21 Aug 2023 12:44:54 -0400 Subject: [PATCH 123/180] [batch] maybe simplify jobs_after_update (#13372) The diff is kinda rough. I think it's easier to just read the new file. It now feels pretty obviously correct. --- batch/batch/driver/main.py | 8 + batch/sql/estimated-current.sql | 268 +++++++++++-------------- batch/sql/jobs-after-update-simple.sql | 146 ++++++++++++++ batch/test/test_batch.py | 10 + build.yaml | 3 + 5 files changed, 288 insertions(+), 147 deletions(-) create mode 100644 batch/sql/jobs-after-update-simple.sql diff --git a/batch/batch/driver/main.py b/batch/batch/driver/main.py index 4c457fe6ba4..5e19915d30c 100644 --- a/batch/batch/driver/main.py +++ b/batch/batch/driver/main.py @@ -1076,6 +1076,14 @@ async def check(tx): OR actual_n_cancelled_ready_jobs != expected_n_cancelled_ready_jobs OR actual_n_cancelled_running_jobs != expected_n_cancelled_running_jobs OR actual_n_cancelled_creating_jobs != expected_n_cancelled_creating_jobs + OR expected_n_ready_jobs != 0 + OR expected_ready_cores_mcpu != 0 + OR expected_n_running_jobs != 0 + OR expected_running_cores_mcpu != 0 + OR expected_n_creating_jobs != 0 + OR expected_n_cancelled_ready_jobs != 0 + OR expected_n_cancelled_running_jobs != 0 + OR expected_n_cancelled_creating_jobs != 0 LOCK IN SHARE MODE; ''' ) diff --git a/batch/sql/estimated-current.sql b/batch/sql/estimated-current.sql index 6a0a97c9044..f2fcccf1747 100644 --- a/batch/sql/estimated-current.sql +++ b/batch/sql/estimated-current.sql @@ -654,164 +654,138 @@ BEGIN DECLARE cur_n_tokens INT; DECLARE rand_token INT; - SELECT user INTO cur_user FROM batches WHERE id = NEW.batch_id; + DECLARE always_run boolean; + DECLARE cores_mcpu bigint; - SET cur_batch_cancelled = EXISTS (SELECT TRUE - FROM batches_cancelled - WHERE id = NEW.batch_id - LOCK IN SHARE MODE); + DECLARE was_marked_cancelled boolean; + DECLARE was_cancelled boolean; + DECLARE was_cancellable boolean; - SELECT n_tokens INTO cur_n_tokens FROM globals LOCK IN SHARE MODE; - SET rand_token = FLOOR(RAND() * cur_n_tokens); + DECLARE now_marked_cancelled boolean; + DECLARE now_cancelled boolean; + DECLARE now_cancellable boolean; - IF OLD.state = 'Ready' THEN - IF NOT (OLD.always_run OR OLD.cancelled OR cur_batch_cancelled) THEN - # cancellable - INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, n_ready_cancellable_jobs, ready_cancellable_cores_mcpu) - VALUES (OLD.batch_id, NEW.update_id, OLD.inst_coll, rand_token, -1, -OLD.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_ready_cancellable_jobs = n_ready_cancellable_jobs - 1, - ready_cancellable_cores_mcpu = ready_cancellable_cores_mcpu - OLD.cores_mcpu; - END IF; + DECLARE was_ready boolean; + DECLARE now_ready boolean; - IF NOT OLD.always_run AND (OLD.cancelled OR cur_batch_cancelled) THEN - # cancelled - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_cancelled_ready_jobs) - VALUES (cur_user, OLD.inst_coll, rand_token, -1) - ON DUPLICATE KEY UPDATE - n_cancelled_ready_jobs = n_cancelled_ready_jobs - 1; - ELSE - # runnable - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_ready_jobs, ready_cores_mcpu) - VALUES (cur_user, OLD.inst_coll, rand_token, -1, -OLD.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_ready_jobs = n_ready_jobs - 1, - ready_cores_mcpu = ready_cores_mcpu - OLD.cores_mcpu; - END IF; - ELSEIF OLD.state = 'Running' THEN - IF NOT (OLD.always_run OR cur_batch_cancelled) THEN - # cancellable - INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, n_running_cancellable_jobs, running_cancellable_cores_mcpu) - VALUES (OLD.batch_id, NEW.update_id, OLD.inst_coll, rand_token, -1, -OLD.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_running_cancellable_jobs = n_running_cancellable_jobs - 1, - running_cancellable_cores_mcpu = running_cancellable_cores_mcpu - OLD.cores_mcpu; - END IF; + DECLARE was_running boolean; + DECLARE now_running boolean; - # state = 'Running' jobs cannot be cancelled at the job level - IF NOT OLD.always_run AND cur_batch_cancelled THEN - # cancelled - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_cancelled_running_jobs) - VALUES (cur_user, OLD.inst_coll, rand_token, -1) - ON DUPLICATE KEY UPDATE - n_cancelled_running_jobs = n_cancelled_running_jobs - 1; - ELSE - # running - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_running_jobs, running_cores_mcpu) - VALUES (cur_user, OLD.inst_coll, rand_token, -1, -OLD.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_running_jobs = n_running_jobs - 1, - running_cores_mcpu = running_cores_mcpu - OLD.cores_mcpu; - END IF; - ELSEIF OLD.state = 'Creating' THEN - IF NOT (OLD.always_run OR cur_batch_cancelled) THEN - # cancellable - INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, n_creating_cancellable_jobs) - VALUES (OLD.batch_id, NEW.update_id, OLD.inst_coll, rand_token, -1) - ON DUPLICATE KEY UPDATE - n_creating_cancellable_jobs = n_creating_cancellable_jobs - 1; - END IF; + DECLARE was_creating boolean; + DECLARE now_creating boolean; - # state = 'Creating' jobs cannot be cancelled at the job level - IF NOT OLD.always_run AND cur_batch_cancelled THEN - # cancelled - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_cancelled_creating_jobs) - VALUES (cur_user, OLD.inst_coll, rand_token, -1) - ON DUPLICATE KEY UPDATE - n_cancelled_creating_jobs = n_cancelled_creating_jobs - 1; - ELSE - # creating - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_creating_jobs) - VALUES (cur_user, OLD.inst_coll, rand_token, -1) - ON DUPLICATE KEY UPDATE - n_creating_jobs = n_creating_jobs - 1; - END IF; + DECLARE delta_n_ready_cancellable_jobs int; + DECLARE delta_ready_cancellable_cores_mcpu bigint; + DECLARE delta_n_ready_jobs int; + DECLARE delta_ready_cores_mcpu bigint; + DECLARE delta_n_cancelled_ready_jobs int; - END IF; + DECLARE delta_n_running_cancellable_jobs int; + DECLARE delta_running_cancellable_cores_mcpu bigint; + DECLARE delta_n_running_jobs int; + DECLARE delta_running_cores_mcpu bigint; + DECLARE delta_n_cancelled_running_jobs int; - IF NEW.state = 'Ready' THEN - IF NOT (NEW.always_run OR NEW.cancelled OR cur_batch_cancelled) THEN - # cancellable - INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, n_ready_cancellable_jobs, ready_cancellable_cores_mcpu) - VALUES (NEW.batch_id, NEW.update_id, NEW.inst_coll, rand_token, 1, NEW.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_ready_cancellable_jobs = n_ready_cancellable_jobs + 1, - ready_cancellable_cores_mcpu = ready_cancellable_cores_mcpu + NEW.cores_mcpu; - END IF; + DECLARE delta_n_creating_cancellable_jobs int; + DECLARE delta_n_creating_jobs int; + DECLARE delta_n_cancelled_creating_jobs int; - IF NOT NEW.always_run AND (NEW.cancelled OR cur_batch_cancelled) THEN - # cancelled - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_cancelled_ready_jobs) - VALUES (cur_user, NEW.inst_coll, rand_token, 1) - ON DUPLICATE KEY UPDATE - n_cancelled_ready_jobs = n_cancelled_ready_jobs + 1; - ELSE - # runnable - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_ready_jobs, ready_cores_mcpu) - VALUES (cur_user, NEW.inst_coll, rand_token, 1, NEW.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_ready_jobs = n_ready_jobs + 1, - ready_cores_mcpu = ready_cores_mcpu + NEW.cores_mcpu; - END IF; - ELSEIF NEW.state = 'Running' THEN - IF NOT (NEW.always_run OR cur_batch_cancelled) THEN - # cancellable - INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, n_running_cancellable_jobs, running_cancellable_cores_mcpu) - VALUES (NEW.batch_id, NEW.update_id, NEW.inst_coll, rand_token, 1, NEW.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_running_cancellable_jobs = n_running_cancellable_jobs + 1, - running_cancellable_cores_mcpu = running_cancellable_cores_mcpu + NEW.cores_mcpu; - END IF; + SELECT user INTO cur_user FROM batches WHERE id = NEW.batch_id; - # state = 'Running' jobs cannot be cancelled at the job level - IF NOT NEW.always_run AND cur_batch_cancelled THEN - # cancelled - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_cancelled_running_jobs) - VALUES (cur_user, NEW.inst_coll, rand_token, 1) - ON DUPLICATE KEY UPDATE - n_cancelled_running_jobs = n_cancelled_running_jobs + 1; - ELSE - # running - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_running_jobs, running_cores_mcpu) - VALUES (cur_user, NEW.inst_coll, rand_token, 1, NEW.cores_mcpu) - ON DUPLICATE KEY UPDATE - n_running_jobs = n_running_jobs + 1, - running_cores_mcpu = running_cores_mcpu + NEW.cores_mcpu; - END IF; - ELSEIF NEW.state = 'Creating' THEN - IF NOT (NEW.always_run OR cur_batch_cancelled) THEN - # cancellable - INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, n_creating_cancellable_jobs) - VALUES (NEW.batch_id, NEW.update_id, NEW.inst_coll, rand_token, 1) - ON DUPLICATE KEY UPDATE - n_creating_cancellable_jobs = n_creating_cancellable_jobs + 1; - END IF; + SET cur_batch_cancelled = EXISTS (SELECT TRUE + FROM batches_cancelled + WHERE id = NEW.batch_id + LOCK IN SHARE MODE); - # state = 'Creating' jobs cannot be cancelled at the job level - IF NOT NEW.always_run AND cur_batch_cancelled THEN - # cancelled - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_cancelled_creating_jobs) - VALUES (cur_user, NEW.inst_coll, rand_token, 1) - ON DUPLICATE KEY UPDATE - n_cancelled_creating_jobs = n_cancelled_creating_jobs + 1; - ELSE - # creating - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_creating_jobs) - VALUES (cur_user, NEW.inst_coll, rand_token, 1) - ON DUPLICATE KEY UPDATE - n_creating_jobs = n_creating_jobs + 1; - END IF; - END IF; + SELECT n_tokens INTO cur_n_tokens FROM globals LOCK IN SHARE MODE; + SET rand_token = FLOOR(RAND() * cur_n_tokens); + + SET always_run = old.always_run; # always_run is immutable + SET cores_mcpu = old.cores_mcpu; # cores_mcpu is immutable + + SET was_marked_cancelled = old.cancelled OR cur_batch_cancelled; + SET was_cancelled = NOT always_run AND was_marked_cancelled; + SET was_cancellable = NOT always_run AND NOT was_marked_cancelled; + + SET now_marked_cancelled = new.cancelled or cur_batch_cancelled; + SET now_cancelled = NOT always_run AND now_marked_cancelled; + SET now_cancellable = NOT always_run AND NOT now_marked_cancelled; + + # NB: was_cancelled => now_cancelled b/c you cannot be uncancelled + + SET was_ready = old.state = 'Ready'; + SET now_ready = new.state = 'Ready'; + SET was_running = old.state = 'Running'; + SET now_running = new.state = 'Running'; + SET was_creating = old.state = 'Creating'; + SET now_creating = new.state = 'Creating'; + + SET delta_n_ready_cancellable_jobs = (-1 * was_ready * was_cancellable ) + (now_ready * now_cancellable ) ; + SET delta_n_ready_jobs = (-1 * was_ready * (NOT was_cancelled)) + (now_ready * (NOT now_cancelled)); + SET delta_n_cancelled_ready_jobs = (-1 * was_ready * was_cancelled ) + (now_ready * now_cancelled ) ; + + SET delta_n_running_cancellable_jobs = (-1 * was_running * was_cancellable ) + (now_running * now_cancellable ) ; + SET delta_n_running_jobs = (-1 * was_running * (NOT was_cancelled)) + (now_running * (NOT now_cancelled)); + SET delta_n_cancelled_running_jobs = (-1 * was_running * was_cancelled ) + (now_running * now_cancelled ) ; + + SET delta_n_creating_cancellable_jobs = (-1 * was_creating * was_cancellable ) + (now_creating * now_cancellable ) ; + SET delta_n_creating_jobs = (-1 * was_creating * (NOT was_cancelled)) + (now_creating * (NOT now_cancelled)); + SET delta_n_cancelled_creating_jobs = (-1 * was_creating * was_cancelled ) + (now_creating * now_cancelled ) ; + + SET delta_ready_cancellable_cores_mcpu = delta_n_ready_cancellable_jobs * cores_mcpu; + SET delta_ready_cores_mcpu = delta_n_ready_jobs * cores_mcpu; + + SET delta_running_cancellable_cores_mcpu = delta_n_running_cancellable_jobs * cores_mcpu; + SET delta_running_cores_mcpu = delta_n_running_jobs * cores_mcpu; + + INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, + n_ready_cancellable_jobs, + ready_cancellable_cores_mcpu, + n_creating_cancellable_jobs, + n_running_cancellable_jobs, + running_cancellable_cores_mcpu) + VALUES (NEW.batch_id, NEW.update_id, NEW.inst_coll, rand_token, + delta_n_ready_cancellable_jobs, + delta_ready_cancellable_cores_mcpu, + delta_n_creating_cancellable_jobs, + delta_n_running_cancellable_jobs, + delta_running_cancellable_cores_mcpu) + ON DUPLICATE KEY UPDATE + n_ready_cancellable_jobs = n_ready_cancellable_jobs + delta_n_ready_cancellable_jobs, + ready_cancellable_cores_mcpu = ready_cancellable_cores_mcpu + delta_ready_cancellable_cores_mcpu, + n_creating_cancellable_jobs = n_creating_cancellable_jobs + delta_n_creating_cancellable_jobs, + n_running_cancellable_jobs = n_running_cancellable_jobs + delta_n_running_cancellable_jobs, + running_cancellable_cores_mcpu = running_cancellable_cores_mcpu + delta_running_cancellable_cores_mcpu; + + INSERT INTO user_inst_coll_resources (user, inst_coll, token, + n_ready_jobs, + n_running_jobs, + n_creating_jobs, + ready_cores_mcpu, + running_cores_mcpu, + n_cancelled_ready_jobs, + n_cancelled_running_jobs, + n_cancelled_creating_jobs + ) + VALUES (cur_user, NEW.inst_coll, rand_token, + delta_n_ready_jobs, + delta_n_running_jobs, + delta_n_creating_jobs, + delta_ready_cores_mcpu, + delta_running_cores_mcpu, + delta_n_cancelled_ready_jobs, + delta_n_cancelled_running_jobs, + delta_n_cancelled_creating_jobs + ) + ON DUPLICATE KEY UPDATE + n_ready_jobs = n_ready_jobs + delta_n_ready_jobs, + n_running_jobs = n_running_jobs + delta_n_running_jobs, + n_creating_jobs = n_creating_jobs + delta_n_creating_jobs, + ready_cores_mcpu = ready_cores_mcpu + delta_ready_cores_mcpu, + running_cores_mcpu = running_cores_mcpu + delta_running_cores_mcpu, + n_cancelled_ready_jobs = n_cancelled_ready_jobs + delta_n_cancelled_ready_jobs, + n_cancelled_running_jobs = n_cancelled_running_jobs + delta_n_cancelled_running_jobs, + n_cancelled_creating_jobs = n_cancelled_creating_jobs + delta_n_cancelled_creating_jobs; END $$ DROP TRIGGER IF EXISTS attempt_resources_after_insert $$ diff --git a/batch/sql/jobs-after-update-simple.sql b/batch/sql/jobs-after-update-simple.sql new file mode 100644 index 00000000000..48553796081 --- /dev/null +++ b/batch/sql/jobs-after-update-simple.sql @@ -0,0 +1,146 @@ +DELIMITER $$ + +DROP TRIGGER IF EXISTS jobs_after_update $$ +CREATE TRIGGER jobs_after_update AFTER UPDATE ON jobs +FOR EACH ROW +BEGIN + DECLARE cur_user VARCHAR(100); + DECLARE cur_batch_cancelled BOOLEAN; + DECLARE cur_n_tokens INT; + DECLARE rand_token INT; + + DECLARE always_run boolean; + DECLARE cores_mcpu bigint; + + DECLARE was_marked_cancelled boolean; + DECLARE was_cancelled boolean; + DECLARE was_cancellable boolean; + + DECLARE now_marked_cancelled boolean; + DECLARE now_cancelled boolean; + DECLARE now_cancellable boolean; + + DECLARE was_ready boolean; + DECLARE now_ready boolean; + + DECLARE was_running boolean; + DECLARE now_running boolean; + + DECLARE was_creating boolean; + DECLARE now_creating boolean; + + DECLARE delta_n_ready_cancellable_jobs int; + DECLARE delta_ready_cancellable_cores_mcpu bigint; + DECLARE delta_n_ready_jobs int; + DECLARE delta_ready_cores_mcpu bigint; + DECLARE delta_n_cancelled_ready_jobs int; + + DECLARE delta_n_running_cancellable_jobs int; + DECLARE delta_running_cancellable_cores_mcpu bigint; + DECLARE delta_n_running_jobs int; + DECLARE delta_running_cores_mcpu bigint; + DECLARE delta_n_cancelled_running_jobs int; + + DECLARE delta_n_creating_cancellable_jobs int; + DECLARE delta_n_creating_jobs int; + DECLARE delta_n_cancelled_creating_jobs int; + + SELECT user INTO cur_user FROM batches WHERE id = NEW.batch_id; + + SET cur_batch_cancelled = EXISTS (SELECT TRUE + FROM batches_cancelled + WHERE id = NEW.batch_id + LOCK IN SHARE MODE); + + SELECT n_tokens INTO cur_n_tokens FROM globals LOCK IN SHARE MODE; + SET rand_token = FLOOR(RAND() * cur_n_tokens); + + SET always_run = old.always_run; # always_run is immutable + SET cores_mcpu = old.cores_mcpu; # cores_mcpu is immutable + + SET was_marked_cancelled = old.cancelled OR cur_batch_cancelled; + SET was_cancelled = NOT always_run AND was_marked_cancelled; + SET was_cancellable = NOT always_run AND NOT was_marked_cancelled; + + SET now_marked_cancelled = new.cancelled or cur_batch_cancelled; + SET now_cancelled = NOT always_run AND now_marked_cancelled; + SET now_cancellable = NOT always_run AND NOT now_marked_cancelled; + + # NB: was_cancelled implies now_cancelled b/c you cannot be uncancelled + + SET was_ready = old.state = 'Ready'; + SET now_ready = new.state = 'Ready'; + SET was_running = old.state = 'Running'; + SET now_running = new.state = 'Running'; + SET was_creating = old.state = 'Creating'; + SET now_creating = new.state = 'Creating'; + + SET delta_n_ready_cancellable_jobs = (-1 * was_ready * was_cancellable ) + (now_ready * now_cancellable ) ; + SET delta_n_ready_jobs = (-1 * was_ready * (NOT was_cancelled)) + (now_ready * (NOT now_cancelled)); + SET delta_n_cancelled_ready_jobs = (-1 * was_ready * was_cancelled ) + (now_ready * now_cancelled ) ; + + SET delta_n_running_cancellable_jobs = (-1 * was_running * was_cancellable ) + (now_running * now_cancellable ) ; + SET delta_n_running_jobs = (-1 * was_running * (NOT was_cancelled)) + (now_running * (NOT now_cancelled)); + SET delta_n_cancelled_running_jobs = (-1 * was_running * was_cancelled ) + (now_running * now_cancelled ) ; + + SET delta_n_creating_cancellable_jobs = (-1 * was_creating * was_cancellable ) + (now_creating * now_cancellable ) ; + SET delta_n_creating_jobs = (-1 * was_creating * (NOT was_cancelled)) + (now_creating * (NOT now_cancelled)); + SET delta_n_cancelled_creating_jobs = (-1 * was_creating * was_cancelled ) + (now_creating * now_cancelled ) ; + + SET delta_ready_cancellable_cores_mcpu = delta_n_ready_cancellable_jobs * cores_mcpu; + SET delta_ready_cores_mcpu = delta_n_ready_jobs * cores_mcpu; + + SET delta_running_cancellable_cores_mcpu = delta_n_running_cancellable_jobs * cores_mcpu; + SET delta_running_cores_mcpu = delta_n_running_jobs * cores_mcpu; + + INSERT INTO batch_inst_coll_cancellable_resources (batch_id, update_id, inst_coll, token, + n_ready_cancellable_jobs, + ready_cancellable_cores_mcpu, + n_creating_cancellable_jobs, + n_running_cancellable_jobs, + running_cancellable_cores_mcpu) + VALUES (NEW.batch_id, NEW.update_id, NEW.inst_coll, rand_token, + delta_n_ready_cancellable_jobs, + delta_ready_cancellable_cores_mcpu, + delta_n_creating_cancellable_jobs, + delta_n_running_cancellable_jobs, + delta_running_cancellable_cores_mcpu) + ON DUPLICATE KEY UPDATE + n_ready_cancellable_jobs = n_ready_cancellable_jobs + delta_n_ready_cancellable_jobs, + ready_cancellable_cores_mcpu = ready_cancellable_cores_mcpu + delta_ready_cancellable_cores_mcpu, + n_creating_cancellable_jobs = n_creating_cancellable_jobs + delta_n_creating_cancellable_jobs, + n_running_cancellable_jobs = n_running_cancellable_jobs + delta_n_running_cancellable_jobs, + running_cancellable_cores_mcpu = running_cancellable_cores_mcpu + delta_running_cancellable_cores_mcpu; + + INSERT INTO user_inst_coll_resources (user, inst_coll, token, + n_ready_jobs, + n_running_jobs, + n_creating_jobs, + ready_cores_mcpu, + running_cores_mcpu, + n_cancelled_ready_jobs, + n_cancelled_running_jobs, + n_cancelled_creating_jobs + ) + VALUES (cur_user, NEW.inst_coll, rand_token, + delta_n_ready_jobs, + delta_n_running_jobs, + delta_n_creating_jobs, + delta_ready_cores_mcpu, + delta_running_cores_mcpu, + delta_n_cancelled_ready_jobs, + delta_n_cancelled_running_jobs, + delta_n_cancelled_creating_jobs + ) + ON DUPLICATE KEY UPDATE + n_ready_jobs = n_ready_jobs + delta_n_ready_jobs, + n_running_jobs = n_running_jobs + delta_n_running_jobs, + n_creating_jobs = n_creating_jobs + delta_n_creating_jobs, + ready_cores_mcpu = ready_cores_mcpu + delta_ready_cores_mcpu, + running_cores_mcpu = running_cores_mcpu + delta_running_cores_mcpu, + n_cancelled_ready_jobs = n_cancelled_ready_jobs + delta_n_cancelled_ready_jobs, + n_cancelled_running_jobs = n_cancelled_running_jobs + delta_n_cancelled_running_jobs, + n_cancelled_creating_jobs = n_cancelled_creating_jobs + delta_n_cancelled_creating_jobs; +END $$ + +DELIMITER ; diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 0ebf78ca2ae..bb07947e8dc 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -1486,6 +1486,16 @@ def test_job_private_instance_cancel(client: BatchClient): assert status['state'] == 'Cancelled', str((status, b.debug_info())) +def test_always_run_job_private_instance_cancel(client: BatchClient): + bb = create_batch(client) + resources = {'machine_type': smallest_machine_type()} + j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources, always_run=True) + b = bb.submit() + b.cancel() + status = j.wait() + assert status['state'] == 'Success', str((status, b.debug_info())) + + def test_create_fast_path_more_than_one_job(client: BatchClient): bb = create_batch(client) bb.create_job(DOCKER_ROOT_IMAGE, ['true']) diff --git a/build.yaml b/build.yaml index 71016672804..7a4e4b67e31 100644 --- a/build.yaml +++ b/build.yaml @@ -2201,6 +2201,9 @@ steps: - name: add-billing-index-token script: /io/sql/add-billing-index-token.sql online: true + - name: jobs-after-update-simple.sql + script: /io/sql/jobs-after-update-simple.sql + online: true inputs: - from: /repo/batch/sql to: /io/sql From e49c6a3d021ec7106246beeda41e6060dc7242a8 Mon Sep 17 00:00:00 2001 From: jigold Date: Mon, 21 Aug 2023 16:03:42 -0400 Subject: [PATCH 124/180] [batch_client.aioclient] Get rid of BatchBuilder (#13458) This PR refactors the aioclient to merge the functionality of Batch and BatchBuilder into just a single Batch object. The reason for making this change is to make adding job groups simpler. I will follow up with a change to Jobs after this merges. I apologize for the number of line changes. Most are just renaming `bb -> b` in the tests. --- batch/test/test_accounts.py | 143 ++-- batch/test/test_aioclient.py | 6 +- batch/test/test_batch.py | 676 +++++++++--------- batch/test/test_dag.py | 24 +- batch/test/test_scale.py | 2 +- batch/test/utils.py | 8 +- ci/ci/github.py | 2 +- hail/python/hail/backend/service_backend.py | 8 +- hail/python/hail/methods/qc.py | 46 +- hail/python/hailtop/batch/backend.py | 61 +- hail/python/hailtop/batch_client/aioclient.py | 220 +++--- hail/python/hailtop/batch_client/client.py | 89 +-- hail/python/test/hailtop/batch/test_batch.py | 2 +- 13 files changed, 628 insertions(+), 659 deletions(-) diff --git a/batch/test/test_accounts.py b/batch/test/test_accounts.py index 8e4f36ec7eb..5a2673ae3d2 100644 --- a/batch/test/test_accounts.py +++ b/batch/test/test_accounts.py @@ -77,9 +77,9 @@ async def test_bad_token(): token = session_id_encode_to_str(secrets.token_bytes(32)) bc = await BatchClient.create('test', _token=token) try: - bb = create_batch(bc) - bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - b = await bb.submit() + b = create_batch(bc) + b.create_job(DOCKER_ROOT_IMAGE, ['false']) + await b.submit() assert False, str(await b.debug_info()) except httpx.ClientResponseError as e: assert e.status == 401 @@ -180,10 +180,10 @@ async def test_close_billing_project_with_pending_batch_update_does_not_error( project = new_billing_project await dev_client.add_user("test", project) client = await make_client(project) - bb = create_batch(client) - bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - b = await bb._open_batch() - update_id = await bb._create_update(b.id) + b = create_batch(client) + b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) + await b._open_batch() + update_id = await b._create_update() with BatchProgressBar() as pbar: process = { 'type': 'docker', @@ -193,7 +193,7 @@ async def test_close_billing_project_with_pending_batch_update_does_not_error( } spec = {'always_run': False, 'job_id': 1, 'parent_ids': [], 'process': process} with pbar.with_task('submitting jobs', total=1) as pbar_task: - await bb._submit_jobs(b.id, update_id, [orjson.dumps(spec)], 1, pbar_task) + await b._submit_jobs(update_id, [orjson.dumps(spec)], 1, pbar_task) try: await dev_client.close_billing_project(project) except httpx.ClientResponseError as e: @@ -355,15 +355,15 @@ async def test_billing_project_accrued_costs( def approx_equal(x, y, tolerance=1e-10): return abs(x - y) <= tolerance - bb = create_batch(client) - j1_1 = bb.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) - j1_2 = bb.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) - b1 = await bb.submit() + b1 = create_batch(client) + j1_1 = b1.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) + j1_2 = b1.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) + await b1.submit() - bb = create_batch(client) - j2_1 = bb.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) - j2_2 = bb.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) - b2 = await bb.submit() + b2 = create_batch(client) + j2_1 = b2.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) + j2_2 = b2.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) + await b2.submit() await b1.wait() await b2.wait() @@ -409,8 +409,8 @@ async def test_billing_limit_zero( client = await make_client(project) try: - bb = create_batch(client) - b = await bb.submit() + b = create_batch(client) + await b.submit() except httpx.ClientResponseError as e: assert e.status == 403 and 'has exceeded the budget' in e.body else: @@ -434,20 +434,20 @@ async def test_billing_limit_tiny( client = await make_client(project) - bb = create_batch(client) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - j2 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j1]) - j3 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j2]) - j4 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j3]) - j5 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j4]) - j6 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j5]) - j7 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j6]) - j8 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j7]) - j9 = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j8]) - bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '5'], parents=[j9]) - batch = await bb.submit() - batch_status = await batch.wait() - assert batch_status['state'] == 'cancelled', str(await batch.debug_info()) + b = create_batch(client) + j1 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) + j2 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j1]) + j3 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j2]) + j4 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j3]) + j5 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j4]) + j6 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j5]) + j7 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j6]) + j8 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j7]) + j9 = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30'], parents=[j8]) + b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '5'], parents=[j9]) + await b.submit() + batch_status = await b.wait() + assert batch_status['state'] == 'cancelled', str(await b.debug_info()) async def search_batches(client, expected_batch_id, q) -> Tuple[bool, List[int]]: @@ -476,10 +476,10 @@ async def test_user_can_access_batch_made_by_other_user_in_shared_billing_projec user1_client = await make_client(project) b = create_batch(user1_client) j = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - b_handle = await b.submit() + await b.submit() user2_client = dev_client - user2_batch = await user2_client.get_batch(b_handle.id) + user2_batch = await user2_client.get_batch(b.id) user2_job = await user2_client.get_job(j.batch_id, j.job_id) await user2_job.attempts() @@ -487,50 +487,50 @@ async def test_user_can_access_batch_made_by_other_user_in_shared_billing_projec await user2_job.status() # list batches results for user1 - found, batches = await search_batches(user1_client, b_handle.id, q='') - assert found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user1_client, b.id, q='') + assert found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user1_client, b_handle.id, q=f'billing_project:{project}') - assert found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user1_client, b.id, q=f'billing_project:{project}') + assert found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user1_client, b_handle.id, q='user:test') - assert found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user1_client, b.id, q='user:test') + assert found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user1_client, b_handle.id, q='billing_project:foo') - assert not found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user1_client, b.id, q='billing_project:foo') + assert not found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user1_client, b_handle.id, q=None) - assert found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user1_client, b.id, q=None) + assert found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user1_client, b_handle.id, q='user:test-dev') - assert not found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user1_client, b.id, q='user:test-dev') + assert not found, str((b.id, batches, await b.debug_info())) # list batches results for user2 - found, batches = await search_batches(user2_client, b_handle.id, q='') - assert found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user2_client, b.id, q='') + assert found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user2_client, b_handle.id, q=f'billing_project:{project}') - assert found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user2_client, b.id, q=f'billing_project:{project}') + assert found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user2_client, b_handle.id, q='user:test') - assert found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user2_client, b.id, q='user:test') + assert found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user2_client, b_handle.id, q='billing_project:foo') - assert not found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user2_client, b.id, q='billing_project:foo') + assert not found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user2_client, b_handle.id, q=None) - assert not found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user2_client, b.id, q=None) + assert not found, str((b.id, batches, await b.debug_info())) - found, batches = await search_batches(user2_client, b_handle.id, q='user:test-dev') - assert not found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user2_client, b.id, q='user:test-dev') + assert not found, str((b.id, batches, await b.debug_info())) await user2_batch.status() await user2_batch.cancel() await user2_batch.delete() # make sure deleted batches don't show up - found, batches = await search_batches(user1_client, b_handle.id, q='') - assert not found, str((b_handle.id, batches, await b_handle.debug_info())) + found, batches = await search_batches(user1_client, b.id, q='') + assert not found, str((b.id, batches, await b.debug_info())) async def test_batch_cannot_be_accessed_by_users_outside_the_billing_project( @@ -543,12 +543,12 @@ async def test_batch_cannot_be_accessed_by_users_outside_the_billing_project( assert r['billing_project'] == project user1_client = await make_client(project) - bb = create_batch(user1_client) - j = bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - b = await bb.submit() + b = create_batch(user1_client) + j = b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) + await b.submit() user2_client = dev_client - user2_batch = Batch(user2_client, b.id, b.attributes, b.token) + user2_batch = Batch(user2_client, b.id, attributes=b.attributes, token=b.token) try: try: @@ -621,7 +621,8 @@ async def test_deleted_open_batches_do_not_prevent_billing_project_closure( try: await dev_client.add_user('test', project) client = await make_client(project) - open_batch = await create_batch(client)._open_batch() + open_batch = create_batch(client) + await open_batch._open_batch() await open_batch.delete() finally: await dev_client.close_billing_project(project) @@ -637,17 +638,17 @@ async def test_billing_project_case_sensitive(dev_client: BatchClient, new_billi dev_client.reset_billing_project(new_billing_project) # create one batch with the correct billing project - bb = create_batch(dev_client) - bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - await bb.submit() + b = create_batch(dev_client) + b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) + await b.submit() dev_client.reset_billing_project(upper_case_project) # create batch try: - bb = create_batch(dev_client) - bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - await bb.submit() + b = create_batch(dev_client) + b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) + await b.submit() except aiohttp.ClientResponseError as e: assert e.status == 403, e else: diff --git a/batch/test/test_aioclient.py b/batch/test/test_aioclient.py index fda280d2a15..3f69dc3894a 100644 --- a/batch/test/test_aioclient.py +++ b/batch/test/test_aioclient.py @@ -15,9 +15,9 @@ async def client(): async def test_job(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) - b = await bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) + await b.submit() status = await j.wait() assert 'attributes' not in status, str((status, await b.debug_info())) assert status['state'] == 'Success', str((status, await b.debug_info())) diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index bb07947e8dc..90bd224ef1e 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -10,7 +10,7 @@ from hailtop import httpx from hailtop.auth import hail_credentials from hailtop.batch.backend import HAIL_GENETICS_HAILTOP_IMAGE -from hailtop.batch_client.client import BatchClient +from hailtop.batch_client.client import Batch, BatchClient from hailtop.config import get_deploy_config, get_user_config from hailtop.test_utils import skip_in_azure from hailtop.utils import delay_ms_for_try, external_requests_client_session, retry_response_returning_functions @@ -30,9 +30,9 @@ def client(): def test_job(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) + b.submit() status = j.wait() assert 'attributes' not in status, str((status, b.debug_info())) @@ -44,9 +44,9 @@ def test_job(client: BatchClient): def test_job_running_logs(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['bash', '-c', 'echo test && sleep 300']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['bash', '-c', 'echo test && sleep 300']) + b.submit() wait_status = j._wait_for_states('Running') if wait_status['state'] != 'Running': @@ -61,9 +61,9 @@ def test_job_running_logs(client: BatchClient): def test_exit_code_duration(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['bash', '-c', 'exit 7']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['bash', '-c', 'exit 7']) + b.submit() status = j.wait() assert status['exit_code'] == 7, str((status, b.debug_info())) assert isinstance(status['duration'], int), str((status, b.debug_info())) @@ -72,16 +72,16 @@ def test_exit_code_duration(client: BatchClient): def test_attributes(client: BatchClient): a = {'name': 'test_attributes', 'foo': 'bar'} - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], attributes=a) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], attributes=a) + b.submit() assert j.attributes() == a, str(b.debug_info()) def test_garbage_image(client: BatchClient): - bb = create_batch(client) - j = bb.create_job('dsafaaadsf', ['echo', 'test']) - b = bb.submit() + b = create_batch(client) + j = b.create_job('dsafaaadsf', ['echo', 'test']) + b.submit() status = j.wait() assert j._get_exit_codes(status) == {'main': None}, str((status, b.debug_info())) assert j._get_error(status, 'main') is not None, str((status, b.debug_info())) @@ -89,74 +89,74 @@ def test_garbage_image(client: BatchClient): def test_bad_command(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep 5']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['sleep 5']) + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) def test_invalid_resource_requests(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '1', 'memory': '250Gi', 'storage': '1Gi'} - bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) with pytest.raises(httpx.ClientResponseError, match='resource requests.*unsatisfiable'): - bb.submit() + b.submit() - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0', 'memory': '1Gi', 'storage': '1Gi'} - bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) with pytest.raises( httpx.ClientResponseError, match='bad resource request for job.*cpu must be a power of two with a min of 0.25; found.*', ): - bb.submit() + b.submit() - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.1', 'memory': '1Gi', 'storage': '1Gi'} - bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) with pytest.raises( httpx.ClientResponseError, match='bad resource request for job.*cpu must be a power of two with a min of 0.25; found.*', ): - bb.submit() + b.submit() - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'memory': 'foo', 'storage': '1Gi'} - bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) with pytest.raises( httpx.ClientResponseError, match=".*.resources.memory must match regex:.*.resources.memory must be one of:.*", ): - bb.submit() + b.submit() - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'memory': '500Mi', 'storage': '10000000Gi'} - bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) with pytest.raises(httpx.ClientResponseError, match='resource requests.*unsatisfiable'): - bb.submit() + b.submit() - bb = create_batch(client) + b = create_batch(client) resources = {'storage': '10000000Gi', 'machine_type': smallest_machine_type()} - bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) with pytest.raises(httpx.ClientResponseError, match='resource requests.*unsatisfiable'): - bb.submit() + b.submit() def test_out_of_memory(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25'} - j = bb.create_job('python:3.6-slim-stretch', ['python', '-c', 'x = "a" * (2 * 1024**3)'], resources=resources) - b = bb.submit() + j = b.create_job('python:3.6-slim-stretch', ['python', '-c', 'x = "a" * (2 * 1024**3)'], resources=resources) + b.submit() status = j.wait() assert j._get_out_of_memory(status, 'main'), str((status, b.debug_info())) def test_out_of_storage(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'fallocate -l 100GiB /foo'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'fallocate -l 100GiB /foo'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() @@ -164,12 +164,12 @@ def test_out_of_storage(client: BatchClient): def test_quota_applies_to_volume(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25'} - j = bb.create_job( + j = b.create_job( os.environ['HAIL_VOLUME_IMAGE'], ['/bin/sh', '-c', 'fallocate -l 100GiB /data/foo'], resources=resources ) - b = bb.submit() + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() @@ -178,41 +178,41 @@ def test_quota_applies_to_volume(client: BatchClient): def test_relative_volume_path_is_actually_absolute(client: BatchClient): # https://github.com/hail-is/hail/pull/12990#issuecomment-1540332989 - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25'} - j = bb.create_job( + j = b.create_job( os.environ['HAIL_VOLUME_IMAGE'], ['/bin/sh', '-c', 'ls / && ls . && ls /relative_volume && ! ls relative_volume'], resources=resources, ) - b = bb.submit() + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) def test_quota_shared_by_io_and_rootfs(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'storage': '10Gi'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'fallocate -l 7GiB /foo'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'fallocate -l 7GiB /foo'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'storage': '10Gi'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'fallocate -l 7GiB /io/foo'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'fallocate -l 7GiB /io/foo'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'storage': '10Gi'} - j = bb.create_job( + j = b.create_job( DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'fallocate -l 7GiB /foo; fallocate -l 7GiB /io/foo'], resources=resources, ) - b = bb.submit() + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() @@ -220,28 +220,28 @@ def test_quota_shared_by_io_and_rootfs(client: BatchClient): def test_nonzero_storage(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'storage': '20Gi'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) @skip_in_azure def test_attached_disk(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'storage': '400Gi'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'df -h; fallocate -l 390GiB /io/foo'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'df -h; fallocate -l 390GiB /io/foo'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) def test_cwd_from_image_workdir(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(os.environ['HAIL_WORKDIR_IMAGE'], ['/bin/sh', '-c', 'pwd']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(os.environ['HAIL_WORKDIR_IMAGE'], ['/bin/sh', '-c', 'pwd']) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) job_log = j.log() @@ -249,8 +249,8 @@ def test_cwd_from_image_workdir(client: BatchClient): def test_unsubmitted_state(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) with pytest.raises(ValueError): j.batch_id # pylint: disable=pointless-statement @@ -268,13 +268,13 @@ def test_unsubmitted_state(client: BatchClient): def test_list_batches_v1(client: BatchClient): tag = secrets.token_urlsafe(64) - bb1 = create_batch(client, attributes={'tag': tag, 'name': 'b1'}) - bb1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) - b1 = bb1.submit() + b1 = create_batch(client, attributes={'tag': tag, 'name': 'b1'}) + b1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) + b1.submit() - bb2 = create_batch(client, attributes={'tag': tag, 'name': 'b2'}) - bb2.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) - b2 = bb2.submit() + b2 = create_batch(client, attributes={'tag': tag, 'name': 'b2'}) + b2.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) + b2.submit() batch_id_test_universe = {b1.id, b2.id} @@ -316,17 +316,13 @@ def assert_batch_ids(expected: Set[int], q=None): def test_list_batches_v2(client: BatchClient): tag = secrets.token_urlsafe(64) partial_match_prefix = secrets.token_urlsafe(10) - bb1 = create_batch( - client, attributes={'tag': tag, 'name': 'b1', 'partial_match_name': f'{partial_match_prefix}-b1'} - ) - bb1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) - b1 = bb1.submit() + b1 = create_batch(client, attributes={'tag': tag, 'name': 'b1', 'partial_match_name': f'{partial_match_prefix}-b1'}) + b1.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) + b1.submit() - bb2 = create_batch( - client, attributes={'tag': tag, 'name': 'b2', 'partial_match_name': f'{partial_match_prefix}-b2'} - ) - bb2.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) - b2 = bb2.submit() + b2 = create_batch(client, attributes={'tag': tag, 'name': 'b2', 'partial_match_name': f'{partial_match_prefix}-b2'}) + b2.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) + b2.submit() batch_id_test_universe = {b1.id, b2.id} @@ -556,13 +552,13 @@ def assert_batch_ids(expected: Set[int], q=None): def test_list_jobs_v1(client: BatchClient): - bb = create_batch(client) - j_success = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - j_failure = bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - j_error = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep 5'], attributes={'tag': 'bar'}) - j_running = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '1800'], attributes={'tag': 'foo'}) + b = create_batch(client) + j_success = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + j_failure = b.create_job(DOCKER_ROOT_IMAGE, ['false']) + j_error = b.create_job(DOCKER_ROOT_IMAGE, ['sleep 5'], attributes={'tag': 'bar'}) + j_running = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '1800'], attributes={'tag': 'foo'}) - b = bb.submit() + b.submit() def assert_job_ids(expected, q=None): jobs = b.jobs(q=q) @@ -585,13 +581,13 @@ def assert_job_ids(expected, q=None): def test_list_jobs_v2(client: BatchClient): - bb = create_batch(client) - j_success = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - j_failure = bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - j_error = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep 5'], attributes={'tag': 'bar'}) - j_running = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '1800'], attributes={'tag': 'foo'}) + b = create_batch(client) + j_success = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + j_failure = b.create_job(DOCKER_ROOT_IMAGE, ['false']) + j_error = b.create_job(DOCKER_ROOT_IMAGE, ['sleep 5'], attributes={'tag': 'bar'}) + j_running = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '1800'], attributes={'tag': 'foo'}) - b = bb.submit() + b.submit() def assert_job_ids(expected, q=None): jobs = b.jobs(q=q, version=2) @@ -695,27 +691,27 @@ def assert_job_ids(expected, q=None): def test_include_jobs(client: BatchClient): - bb1 = create_batch(client) + b1 = create_batch(client) for _ in range(2): - bb1.create_job(DOCKER_ROOT_IMAGE, ['true']) - b1 = bb1.submit() + b1.create_job(DOCKER_ROOT_IMAGE, ['true']) + b1.submit() s = b1.status() assert 'jobs' not in s, str((s, b1.debug_info())) def test_fail(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['false']) + b.submit() status = j.wait() assert j._get_exit_code(status, 'main') == 1, str((status, b.debug_info())) def test_unknown_image(client: BatchClient): DOCKER_PREFIX = os.environ['DOCKER_PREFIX'] - bb = create_batch(client) - j = bb.create_job(f'{DOCKER_PREFIX}/does-not-exist', ['echo', 'test']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(f'{DOCKER_PREFIX}/does-not-exist', ['echo', 'test']) + b.submit() status = j.wait() try: assert j._get_exit_code(status, 'main') is None @@ -728,10 +724,10 @@ def test_unknown_image(client: BatchClient): @skip_in_azure def test_invalid_gar(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) # GCP projects can't be strictly numeric - j = bb.create_job('us-docker.pkg.dev/1/does-not-exist', ['echo', 'test']) - b = bb.submit() + j = b.create_job('us-docker.pkg.dev/1/does-not-exist', ['echo', 'test']) + b.submit() status = j.wait() try: assert j._get_exit_code(status, 'main') is None @@ -743,9 +739,9 @@ def test_invalid_gar(client: BatchClient): def test_running_job_log_and_status(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '300']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '300']) + b.submit() while True: if j.status()['state'] == 'Running' or j.is_complete(): @@ -757,9 +753,9 @@ def test_running_job_log_and_status(client: BatchClient): def test_deleted_job_log(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) + b.submit() j.wait() b.delete() @@ -773,9 +769,9 @@ def test_deleted_job_log(client: BatchClient): def test_delete_batch(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) + b.submit() b.delete() # verify doesn't exist @@ -789,9 +785,9 @@ def test_delete_batch(client: BatchClient): def test_cancel_batch(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) + b.submit() status = j.status() assert status['state'] in ('Ready', 'Running'), str((status, b.debug_info())) @@ -823,9 +819,9 @@ def test_get_nonexistent_job(client: BatchClient): def test_get_job(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() j2 = client.get_job(*j.id) status2 = j2.status() @@ -833,11 +829,11 @@ def test_get_job(client: BatchClient): def test_batch(client: BatchClient): - bb = create_batch(client) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '1']) - bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) - b = bb.submit() + b = create_batch(client) + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['false']) + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '1']) + b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) + b.submit() j1.wait() j2.wait() @@ -857,31 +853,31 @@ def test_batch(client: BatchClient): def test_batch_status(client: BatchClient): - bb1 = create_batch(client) - bb1.create_job(DOCKER_ROOT_IMAGE, ['true']) - b1 = bb1.submit() + b1 = create_batch(client) + b1.create_job(DOCKER_ROOT_IMAGE, ['true']) + b1.submit() b1.wait() b1s = b1.status() assert b1s['complete'] and b1s['state'] == 'success', str((b1s, b1.debug_info())) - bb2 = create_batch(client) - bb2.create_job(DOCKER_ROOT_IMAGE, ['false']) - bb2.create_job(DOCKER_ROOT_IMAGE, ['true']) - b2 = bb2.submit() + b2 = create_batch(client) + b2.create_job(DOCKER_ROOT_IMAGE, ['false']) + b2.create_job(DOCKER_ROOT_IMAGE, ['true']) + b2.submit() b2.wait() b2s = b2.status() assert b2s['complete'] and b2s['state'] == 'failure', str((b2s, b2.debug_info())) - bb3 = create_batch(client) - bb3.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) - b3 = bb3.submit() + b3 = create_batch(client) + b3.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) + b3.submit() b3s = b3.status() assert not b3s['complete'] and b3s['state'] == 'running', str((b3s, b3.debug_info())) b3.cancel() - bb4 = create_batch(client) - bb4.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) - b4 = bb4.submit() + b4 = create_batch(client) + b4.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30']) + b4.submit() b4.cancel() b4.wait() b4s = b4.status() @@ -889,9 +885,9 @@ def test_batch_status(client: BatchClient): def test_log_after_failing_job(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'echo test; exit 127']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'echo test; exit 127']) + b.submit() status = j.wait() assert 'attributes' not in status, str((status, b.debug_info())) assert status['state'] == 'Failed', str((status, b.debug_info())) @@ -904,9 +900,9 @@ def test_log_after_failing_job(client: BatchClient): def test_non_utf_8_log(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', "echo -n 'hello \\x80'"]) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', "echo -n 'hello \\x80'"]) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) @@ -915,9 +911,9 @@ def test_non_utf_8_log(client: BatchClient): def test_long_log_line(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'for _ in {0..70000}; do echo -n a; done']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['/bin/sh', '-c', 'for _ in {0..70000}; do echo -n a; done']) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) @@ -955,29 +951,29 @@ def test_authorized_users_only(): def test_cloud_image(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(os.environ['HAIL_CURL_IMAGE'], ['echo', 'test']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(os.environ['HAIL_CURL_IMAGE'], ['echo', 'test']) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) def test_service_account(client: BatchClient): NAMESPACE = os.environ['HAIL_DEFAULT_NAMESPACE'] - bb = create_batch(client) - j = bb.create_job( + b = create_batch(client) + j = b.create_job( os.environ['CI_UTILS_IMAGE'], ['/bin/sh', '-c', 'kubectl version'], service_account={'namespace': NAMESPACE, 'name': 'test-batch-sa'}, ) - b = bb.submit() + b.submit() status = j.wait() assert j._get_exit_code(status, 'main') == 0, str((status, b.debug_info())) def test_port(client: BatchClient): - bb = create_batch(client) - bb.create_job( + b = create_batch(client) + b.create_job( DOCKER_ROOT_IMAGE, [ 'bash', @@ -989,15 +985,15 @@ def test_port(client: BatchClient): ], port=5000, ) - b = bb.submit() + b.submit() batch = b.wait() assert batch['state'] == 'success', str((batch, b.debug_info())) def test_timeout(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30'], timeout=5) - b = bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '30'], timeout=5) + b.submit() status = j.wait() assert status['state'] == 'Error', str((status, b.debug_info())) error_msg = j._get_error(status, 'main') @@ -1006,10 +1002,10 @@ def test_timeout(client: BatchClient): def test_client_max_size(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) for _ in range(4): - bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a' * (900 * 1024)]) - bb.submit() + b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a' * (900 * 1024)]) + b.submit() def test_restartable_insert(client: BatchClient): @@ -1024,12 +1020,12 @@ def every_third_time(): with FailureInjectingClientSession(every_third_time) as session: client = BatchClient('test', session=session) - bb = create_batch(client) + b = create_batch(client) for _ in range(9): - bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a']) + b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a']) - b = bb.submit(max_bunch_size=1) + b.submit(max_bunch_size=1) b = client.get_batch(b.id) # get a batch untainted by the FailureInjectingClientSession status = b.wait() assert status['state'] == 'success', str((status, b.debug_info())) @@ -1039,10 +1035,8 @@ def every_third_time(): def test_create_idempotence(client: BatchClient): token = secrets.token_urlsafe(32) - bb1 = create_batch(client, token=token) - bb2 = create_batch(client, token=token) - b1 = bb1._open_batch() - b2 = bb2._open_batch() + b1 = Batch._open_batch(client, token=token) + b2 = Batch._open_batch(client, token=token) assert b1.id == b2.id @@ -1087,22 +1081,22 @@ async def test_batch_create_validation(): def test_duplicate_parents(client: BatchClient): - bb = create_batch(client) - head = bb.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) - bb.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'tail'], parents=[head, head]) + b = create_batch(client) + head = b.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) + b.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'tail'], parents=[head, head]) try: - batch = bb.submit() + b.submit() except httpx.ClientResponseError as e: assert e.status == 400 else: - assert False, f'should receive a 400 Bad Request {batch.id}' + assert False, f'should receive a 400 Bad Request {b.id}' @skip_in_azure def test_verify_no_access_to_google_metadata_server(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(os.environ['HAIL_CURL_IMAGE'], ['curl', '-fsSL', 'metadata.google.internal', '--max-time', '10']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(os.environ['HAIL_CURL_IMAGE'], ['curl', '-fsSL', 'metadata.google.internal', '--max-time', '10']) + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() @@ -1110,9 +1104,9 @@ def test_verify_no_access_to_google_metadata_server(client: BatchClient): def test_verify_no_access_to_metadata_server(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(os.environ['HAIL_CURL_IMAGE'], ['curl', '-fsSL', '169.254.169.254', '--max-time', '10']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(os.environ['HAIL_CURL_IMAGE'], ['curl', '-fsSL', '169.254.169.254', '--max-time', '10']) + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() @@ -1120,7 +1114,7 @@ def test_verify_no_access_to_metadata_server(client: BatchClient): def test_submit_batch_in_job(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') script = f'''import hailtop.batch as hb backend = hb.ServiceBackend("test", remote_tmpdir="{remote_tmpdir}") @@ -1130,12 +1124,12 @@ def test_submit_batch_in_job(client: BatchClient): b.run() backend.close() ''' - j = bb.create_job( + j = b.create_job( HAIL_GENETICS_HAILTOP_IMAGE, ['/bin/bash', '-c', f'''python3 -c \'{script}\''''], mount_tokens=True, ) - b = bb.submit() + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) @@ -1154,8 +1148,8 @@ def test_cant_submit_to_default_with_other_ns_creds(client: BatchClient): backend.close() ''' - bb = create_batch(client) - j = bb.create_job( + b = create_batch(client) + j = b.create_job( HAIL_GENETICS_HAILTOP_IMAGE, [ '/bin/bash', @@ -1167,7 +1161,7 @@ def test_cant_submit_to_default_with_other_ns_creds(client: BatchClient): ], mount_tokens=True, ) - b = bb.submit() + b.submit() status = j.wait() if NAMESPACE == 'default': assert status['state'] == 'Success', str((status, b.debug_info())) @@ -1177,8 +1171,8 @@ def test_cant_submit_to_default_with_other_ns_creds(client: BatchClient): def test_deploy_config_is_mounted_as_readonly(client: BatchClient): - bb = create_batch(client) - j = bb.create_job( + b = create_batch(client) + j = b.create_job( HAIL_GENETICS_HAILTOP_IMAGE, [ '/bin/bash', @@ -1190,7 +1184,7 @@ def test_deploy_config_is_mounted_as_readonly(client: BatchClient): ], mount_tokens=True, ) - b = bb.submit() + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() @@ -1199,7 +1193,7 @@ def test_deploy_config_is_mounted_as_readonly(client: BatchClient): def test_cannot_contact_other_internal_ips(client: BatchClient): internal_ips = [f'10.128.0.{i}' for i in (10, 11, 12)] - bb = create_batch(client) + b = create_batch(client) script = f''' if [ "$HAIL_BATCH_WORKER_IP" != "{internal_ips[0]}" ] && ! grep -Fq {internal_ips[0]} /etc/hosts; then OTHER_IP={internal_ips[0]} @@ -1211,8 +1205,8 @@ def test_cannot_contact_other_internal_ips(client: BatchClient): curl -fsSL -m 5 $OTHER_IP ''' - j = bb.create_job(os.environ['HAIL_CURL_IMAGE'], ['/bin/bash', '-c', script], port=5000) - b = bb.submit() + j = b.create_job(os.environ['HAIL_CURL_IMAGE'], ['/bin/bash', '-c', script], port=5000) + b.submit() status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() @@ -1223,7 +1217,7 @@ def test_cannot_contact_other_internal_ips(client: BatchClient): def test_hadoop_can_use_cloud_credentials(client: BatchClient): token = os.environ["HAIL_TOKEN"] remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') - bb = create_batch(client) + b = create_batch(client) script = f'''import hail as hl import secrets attempt_token = secrets.token_urlsafe(5) @@ -1231,8 +1225,8 @@ def test_hadoop_can_use_cloud_credentials(client: BatchClient): hl.utils.range_table(10).write(location) hl.read_table(location).show() ''' - j = bb.create_job(HAIL_GENETICS_HAIL_IMAGE, ['/bin/bash', '-c', f'python3 -c >out 2>err \'{script}\'; cat out err']) - b = bb.submit() + j = b.create_job(HAIL_GENETICS_HAIL_IMAGE, ['/bin/bash', '-c', f'python3 -c >out 2>err \'{script}\'; cat out err']) + b.submit() status = j.wait() assert status['state'] == 'Success', f'{j.log(), status}' expected_log = '''+-------+ @@ -1257,25 +1251,25 @@ def test_hadoop_can_use_cloud_credentials(client: BatchClient): def test_user_authentication_within_job(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) cmd = ['bash', '-c', 'hailctl auth user'] - no_token = bb.create_job(HAIL_GENETICS_HAILTOP_IMAGE, cmd, mount_tokens=False) - b = bb.submit() + no_token = b.create_job(HAIL_GENETICS_HAILTOP_IMAGE, cmd, mount_tokens=False) + b.submit() no_token_status = no_token.wait() assert no_token_status['state'] == 'Failed', str((no_token_status, b.debug_info())) def test_verify_access_to_public_internet(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(os.environ['HAIL_CURL_IMAGE'], ['curl', '-fsSL', 'example.com']) - b = bb.submit() + b = create_batch(client) + j = b.create_job(os.environ['HAIL_CURL_IMAGE'], ['curl', '-fsSL', 'example.com']) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) def test_verify_can_tcp_to_localhost(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) script = ''' set -e nc -l -p 5000 & @@ -1284,8 +1278,8 @@ def test_verify_can_tcp_to_localhost(client: BatchClient): '''.lstrip( '\n' ) - j = bb.create_job(os.environ['HAIL_NETCAT_UBUNTU_IMAGE'], command=['/bin/bash', '-c', script]) - b = bb.submit() + j = b.create_job(os.environ['HAIL_NETCAT_UBUNTU_IMAGE'], command=['/bin/bash', '-c', script]) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) job_log = j.log() @@ -1293,7 +1287,7 @@ def test_verify_can_tcp_to_localhost(client: BatchClient): def test_verify_can_tcp_to_127_0_0_1(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) script = ''' set -e nc -l -p 5000 & @@ -1302,8 +1296,8 @@ def test_verify_can_tcp_to_127_0_0_1(client: BatchClient): '''.lstrip( '\n' ) - j = bb.create_job(os.environ['HAIL_NETCAT_UBUNTU_IMAGE'], command=['/bin/bash', '-c', script]) - b = bb.submit() + j = b.create_job(os.environ['HAIL_NETCAT_UBUNTU_IMAGE'], command=['/bin/bash', '-c', script]) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) job_log = j.log() @@ -1311,7 +1305,7 @@ def test_verify_can_tcp_to_127_0_0_1(client: BatchClient): def test_verify_can_tcp_to_self_ip(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) script = ''' set -e nc -l -p 5000 & @@ -1320,8 +1314,8 @@ def test_verify_can_tcp_to_self_ip(client: BatchClient): '''.lstrip( '\n' ) - j = bb.create_job(os.environ['HAIL_NETCAT_UBUNTU_IMAGE'], command=['/bin/sh', '-c', script]) - b = bb.submit() + j = b.create_job(os.environ['HAIL_NETCAT_UBUNTU_IMAGE'], command=['/bin/sh', '-c', script]) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) job_log = j.log() @@ -1329,12 +1323,12 @@ def test_verify_can_tcp_to_self_ip(client: BatchClient): def test_verify_private_network_is_restricted(client: BatchClient): - bb = create_batch(client) - bb.create_job( + b = create_batch(client) + b.create_job( os.environ['HAIL_CURL_IMAGE'], command=['curl', 'internal.hail', '--connect-timeout', '60'], network='private' ) try: - bb.submit() + b.submit() except httpx.ClientResponseError as err: assert err.status == 400 assert 'unauthorized network private' in err.body @@ -1343,10 +1337,10 @@ def test_verify_private_network_is_restricted(client: BatchClient): async def test_old_clients_that_submit_mount_docker_socket_false_is_ok(client: BatchClient): - bb = create_batch(client)._async_builder - b = await bb._open_batch() - bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - update_id = await bb._create_update(b.id) + b = create_batch(client)._async_batch + await b._open_batch() + b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) + update_id = await b._create_update() with BatchProgressBar() as pbar: process = { 'type': 'docker', @@ -1356,14 +1350,14 @@ async def test_old_clients_that_submit_mount_docker_socket_false_is_ok(client: B } spec = {'always_run': False, 'job_id': 1, 'parent_ids': [], 'process': process} with pbar.with_task('submitting jobs', total=1) as pbar_task: - await bb._submit_jobs(b.id, update_id, [orjson.dumps(spec)], 1, pbar_task) + await b._submit_jobs(update_id, [orjson.dumps(spec)], 1, pbar_task) async def test_old_clients_that_submit_mount_docker_socket_true_is_rejected(client: BatchClient): - bb = create_batch(client)._async_builder - b = await bb._open_batch() - bb.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) - update_id = await bb._create_update(b.id) + b = create_batch(client)._async_batch + await b._open_batch() + b.create_job(DOCKER_ROOT_IMAGE, command=['sleep', '30']) + update_id = await b._create_update() with BatchProgressBar() as pbar: process = { 'type': 'docker', @@ -1377,34 +1371,34 @@ async def test_old_clients_that_submit_mount_docker_socket_true_is_rejected(clie httpx.ClientResponseError, match='mount_docker_socket is no longer supported but was set to True in request. Please upgrade.', ): - await bb._submit_jobs(b.id, update_id, [orjson.dumps(spec)], 1, pbar_task) + await b._submit_jobs(update_id, [orjson.dumps(spec)], 1, pbar_task) def test_pool_highmem_instance(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'memory': 'highmem'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'highmem' in status['status']['worker'], str((status, b.debug_info())) def test_pool_highmem_instance_cheapest(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '1', 'memory': '5Gi'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'highmem' in status['status']['worker'], str((status, b.debug_info())) def test_pool_highcpu_instance(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'memory': 'lowmem'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'highcpu' in status['status']['worker'], str((status, b.debug_info())) @@ -1412,60 +1406,60 @@ def test_pool_highcpu_instance(client: BatchClient): @pytest.mark.xfail(os.environ.get('HAIL_CLOUD') == 'azure', strict=True, reason='prices changed in Azure 2023-06-01') def test_pool_highcpu_instance_cheapest(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'memory': '50Mi'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'highcpu' in status['status']['worker'], str((status, b.debug_info())) def test_pool_standard_instance(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '0.25', 'memory': 'standard'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'standard' in status['status']['worker'], str((status, b.debug_info())) def test_pool_standard_instance_cheapest(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'cpu': '1', 'memory': '2.5Gi'} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'standard' in status['status']['worker'], str((status, b.debug_info())) def test_job_private_instance_preemptible(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'machine_type': smallest_machine_type()} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'job-private' in status['status']['worker'], str((status, b.debug_info())) def test_job_private_instance_nonpreemptible(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'machine_type': smallest_machine_type(), 'preemptible': False} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert 'job-private' in status['status']['worker'], str((status, b.debug_info())) def test_job_private_instance_cancel(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'machine_type': smallest_machine_type()} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources) + b.submit() tries = 0 start = time.time() @@ -1487,31 +1481,31 @@ def test_job_private_instance_cancel(client: BatchClient): def test_always_run_job_private_instance_cancel(client: BatchClient): - bb = create_batch(client) + b = create_batch(client) resources = {'machine_type': smallest_machine_type()} - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources, always_run=True) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['true'], resources=resources, always_run=True) + b.submit() b.cancel() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) def test_create_fast_path_more_than_one_job(client: BatchClient): - bb = create_batch(client) - bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() - assert b.submission_info.used_fast_create, b.submission_info + b = create_batch(client) + b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() + assert b._submission_info.used_fast_path, b._submission_info def test_update_batch_no_deps(client: BatchClient): - bb = create_batch(client) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - bb.submit() + b = create_batch(client) + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['false']) + b.submit() j1.wait() - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() j2_status = j2.wait() assert j2_status['state'] == 'Success', str((j2_status, b.debug_info())) @@ -1519,12 +1513,12 @@ def test_update_batch_no_deps(client: BatchClient): def test_update_batch_w_submitted_job_deps(client: BatchClient): - bb = create_batch(client) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + b = create_batch(client) + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() j1.wait() - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j1]) - b = bb.submit() + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j1]) + b.submit() status = j2.wait() assert status['state'] == 'Success', str((status, b.debug_info())) @@ -1532,12 +1526,12 @@ def test_update_batch_w_submitted_job_deps(client: BatchClient): def test_update_batch_w_failing_submitted_job_deps(client: BatchClient): - bb = create_batch(client) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - bb.submit() + b = create_batch(client) + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['false']) + b.submit() - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j1]) - b = bb.submit() + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j1]) + b.submit() status = j2.wait() assert status['state'] == 'Cancelled', str((status, b.debug_info())) @@ -1545,13 +1539,13 @@ def test_update_batch_w_failing_submitted_job_deps(client: BatchClient): def test_update_batch_w_deps_in_update(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j, j1]) - b = bb.submit() + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j, j1]) + b.submit() status = j2.wait() assert status['state'] == 'Success', str((status, b.debug_info())) @@ -1560,15 +1554,15 @@ def test_update_batch_w_deps_in_update(client: BatchClient): def test_update_batch_w_deps_in_update_always_run(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['false']) - bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['false']) + b.submit() j.wait() - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], always_run=True) - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j, j1]) - b = bb.submit() + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['true'], always_run=True) + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j, j1]) + b.submit() j2.wait() assert j1.status()['state'] == 'Success', str((j1.status(), b.debug_info())) @@ -1577,13 +1571,13 @@ def test_update_batch_w_deps_in_update_always_run(client: BatchClient): def test_update_batch_w_failing_deps_in_same_update_and_deps_across_updates(client: BatchClient): - bb = create_batch(client) - j = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - bb.submit() + b = create_batch(client) + j = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['false'], parents=[j]) - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j1]) - b = bb.submit() + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['false'], parents=[j]) + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true'], parents=[j1]) + b.submit() j2_status = j2.wait() assert j.status()['state'] == 'Success', str((j.status(), b.debug_info())) @@ -1592,12 +1586,12 @@ def test_update_batch_w_failing_deps_in_same_update_and_deps_across_updates(clie def test_update_with_always_run(client: BatchClient): - bb = create_batch(client) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) - b = bb.submit() + b = create_batch(client) + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) + b.submit() - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true'], always_run=True, parents=[j1]) - b = bb.submit() + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true'], always_run=True, parents=[j1]) + b.submit() wait_status = j1._wait_for_states('Running') if wait_status['state'] != 'Running': @@ -1613,12 +1607,12 @@ def test_update_with_always_run(client: BatchClient): def test_update_jobs_are_not_serialized(client: BatchClient): - bb = create_batch(client) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) - b = bb.submit() + b = create_batch(client) + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) + b.submit() - j2 = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + j2 = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() j2.wait() @@ -1633,58 +1627,56 @@ def test_update_jobs_are_not_serialized(client: BatchClient): def test_update_batch_w_empty_initial_batch(client: BatchClient): - bb = create_batch(client) - b = bb.submit() + b = create_batch(client) + b.submit() - bb = client.update_batch(b.id) - j1 = bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + j1 = b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() status = j1.wait() assert status['state'] == 'Success', str((status, b.debug_info())) def test_update_batch_w_multiple_empty_updates(client: BatchClient): - bb = create_batch(client) - b = bb.submit() - b = bb.submit() - bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + b = create_batch(client) + b.submit() + b.submit() + b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() status = b.wait() assert status['state'] == 'success', str((status, b.debug_info())) def test_update_batch_w_new_batch_builder(client: BatchClient): - bb = create_batch(client) - b = bb.submit() - bb = client.update_batch(b.id) - bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + b = create_batch(client) + b.submit() + b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() status = b.wait() assert status['state'] == 'success', str((status, b.debug_info())) def test_update_batch_wout_fast_path(client: BatchClient): - bb = create_batch(client) - bb.submit() + b = create_batch(client) + b.submit() for _ in range(4): - bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a' * (900 * 1024)]) - b = bb.submit() - assert not next(iter(b.submission_info.used_fast_update.values())) + b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a' * (900 * 1024)]) + b.submit() + assert not b._submission_info.used_fast_path def test_update_cancelled_batch_wout_fast_path(client: BatchClient): - bb = create_batch(client) - bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) - b = bb.submit() + b = create_batch(client) + b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) + b.submit() b.cancel() try: for _ in range(4): - bb.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a' * (900 * 1024)]) - b = bb.submit() + b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'a' * (900 * 1024)]) + b.submit() except httpx.ClientResponseError as err: assert err.status == 400 assert 'Cannot submit new jobs to a cancelled batch' in err.body @@ -1693,14 +1685,14 @@ def test_update_cancelled_batch_wout_fast_path(client: BatchClient): def test_submit_update_to_cancelled_batch(client: BatchClient): - bb = create_batch(client) - bb.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) - b = bb.submit() + b = create_batch(client) + b.create_job(DOCKER_ROOT_IMAGE, ['sleep', '3600']) + b.submit() b.cancel() try: - bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() except httpx.ClientResponseError as err: assert err.status == 400 assert 'Cannot submit new jobs to a cancelled batch' in err.body @@ -1709,14 +1701,14 @@ def test_submit_update_to_cancelled_batch(client: BatchClient): def test_submit_update_to_deleted_batch(client: BatchClient): - bb = create_batch(client) - b = bb.submit() + b = create_batch(client) + b.submit() b.cancel() b.delete() try: - bb.create_job(DOCKER_ROOT_IMAGE, ['true']) - b = bb.submit() + b.create_job(DOCKER_ROOT_IMAGE, ['true']) + b.submit() except httpx.ClientResponseError as err: assert err.status == 404 else: @@ -1727,14 +1719,14 @@ def test_submit_update_to_deleted_batch(client: BatchClient): def test_region(client: BatchClient): CLOUD = os.environ['HAIL_CLOUD'] - bb = create_batch(client) + b = create_batch(client) if CLOUD == 'gcp': region = 'us-east1' else: assert CLOUD == 'azure' region = 'eastus' - j = bb.create_job(DOCKER_ROOT_IMAGE, ['printenv', 'HAIL_REGION'], regions=[region]) - b = bb.submit() + j = b.create_job(DOCKER_ROOT_IMAGE, ['printenv', 'HAIL_REGION'], regions=[region]) + b.submit() status = j.wait() assert status['state'] == 'Success', str((status, b.debug_info())) assert status['status']['region'] == region, str((status, b.debug_info())) diff --git a/batch/test/test_dag.py b/batch/test/test_dag.py index aed2a698113..c463e372d13 100644 --- a/batch/test/test_dag.py +++ b/batch/test/test_dag.py @@ -24,7 +24,7 @@ def test_simple(client): batch = create_batch(client) head = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head']) batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'tail'], parents=[head]) - batch = batch.submit() + batch.submit() batch.wait() status = legacy_batch_status(batch) assert batch_status_job_counter(status, 'Success') == 2, str((status, batch.debug_info())) @@ -34,10 +34,10 @@ def test_simple(client): def test_missing_parent_is_400(client): try: batch = create_batch(client) - fake_job = aioclient.Job.unsubmitted_job(batch._async_builder, 10000) + fake_job = aioclient.Job.unsubmitted_job(batch._async_batch, 10000) fake_job = Job.from_async_job(fake_job) batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head'], parents=[fake_job]) - batch = batch.submit() + batch.submit() except ValueError as err: assert re.search('parents with invalid job ids', str(err)) return @@ -50,7 +50,7 @@ def test_dag(client): left = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'left'], parents=[head]) right = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'right'], parents=[head]) tail = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'tail'], parents=[left, right]) - batch = batch.submit() + batch.submit() batch.wait() status = legacy_batch_status(batch) @@ -75,7 +75,7 @@ def test_cancel_tail(client): DOCKER_ROOT_IMAGE, command=['/bin/sh', '-c', 'while true; do sleep 86000; done'], parents=[left, right] ) try: - batch = batch.submit() + batch.submit() left.wait() right.wait() finally: @@ -100,7 +100,7 @@ def test_cancel_left_after_tail(client): right = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'right'], parents=[head]) tail = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'tail'], parents=[left, right]) try: - batch = batch.submit() + batch.submit() head.wait() right.wait() finally: @@ -150,7 +150,7 @@ async def callback(request): ) head = b.create_job('alpine:3.8', command=['echo', 'head']) b.create_job('alpine:3.8', command=['echo', 'tail'], parents=[head]) - b = b.submit() + b.submit() await asyncio.wait_for(callback_event.wait(), 5 * 60) callback_body = callback_bodies[0] @@ -206,7 +206,7 @@ def test_input_dependency(client): input_files=[(f'{remote_tmpdir}data1', '/io/data1'), (f'{remote_tmpdir}data2', '/io/data2')], parents=[head], ) - batch = batch.submit() + batch.submit() tail.wait() head_status = head.status() assert head._get_exit_code(head_status, 'main') == 0, str((head_status, batch.debug_info())) @@ -228,7 +228,7 @@ def test_input_dependency_wildcard(client): input_files=[(f'{remote_tmpdir}data1', '/io/data1'), (f'{remote_tmpdir}data2', '/io/data2')], parents=[head], ) - batch = batch.submit() + batch.submit() tail.wait() head_status = head.status() assert head._get_exit_code(head_status, 'input') != 0, str((head_status, batch.debug_info())) @@ -250,7 +250,7 @@ def test_input_dependency_directory(client): input_files=[(f'{remote_tmpdir}test', '/io/test')], parents=[head], ) - batch = batch.submit() + batch.submit() tail.wait() head_status = head.status() assert head._get_exit_code(head_status, 'main') == 0, str((head_status, batch.debug_info())) @@ -267,7 +267,7 @@ def test_always_run_cancel(client): right = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'right'], parents=[head]) tail = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'tail'], parents=[left, right], always_run=True) try: - batch = batch.submit() + batch.submit() right.wait() finally: batch.cancel() @@ -286,7 +286,7 @@ def test_always_run_error(client): batch = create_batch(client) head = batch.create_job(DOCKER_ROOT_IMAGE, command=['/bin/sh', '-c', 'exit 1']) tail = batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'tail'], parents=[head], always_run=True) - batch = batch.submit() + batch.submit() batch.wait() status = legacy_batch_status(batch) assert batch_status_job_counter(status, 'Failed') == 1, str((status, batch.debug_info())) diff --git a/batch/test/test_scale.py b/batch/test/test_scale.py index acf11fbeea3..3f876858644 100644 --- a/batch/test/test_scale.py +++ b/batch/test/test_scale.py @@ -21,7 +21,7 @@ def test_scale(client): sleep_time = random.uniform(0, 30) batch.create_job('alpine:3.8', command=['sleep', str(round(sleep_time))]) - batch = batch.submit() + batch.submit() batch.wait() status = legacy_batch_status(batch) diff --git a/batch/test/utils.py b/batch/test/utils.py index 43a54983b23..7dc7d832020 100644 --- a/batch/test/utils.py +++ b/batch/test/utils.py @@ -11,18 +11,16 @@ @overload -def create_batch(client: bc.BatchClient, **kwargs) -> bc.BatchBuilder: +def create_batch(client: bc.BatchClient, **kwargs) -> bc.Batch: ... @overload -def create_batch(client: aiobc.BatchClient, **kwargs) -> aiobc.BatchBuilder: +def create_batch(client: aiobc.BatchClient, **kwargs) -> aiobc.Batch: ... -def create_batch( - client: Union[bc.BatchClient, aiobc.BatchClient], **kwargs -) -> Union[bc.BatchBuilder, aiobc.BatchBuilder]: +def create_batch(client: Union[bc.BatchClient, aiobc.BatchClient], **kwargs) -> Union[bc.Batch, aiobc.Batch]: name_of_test_method = inspect.stack()[1][3] attrs = kwargs.pop('attributes', {}) # Tests should be able to override the name return client.create_batch(attributes={'name': name_of_test_method, **attrs}, **kwargs) diff --git a/ci/ci/github.py b/ci/ci/github.py index a6fec2f9f4c..65a171e6baa 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -538,7 +538,7 @@ async def _start_build(self, db: Database, batch_client): callback=CALLBACK_URL, ) config.build(batch, self, scope='test') - batch = await batch.submit() + await batch.submit() self.batch = batch except concurrent.futures.CancelledError: raise diff --git a/hail/python/hail/backend/service_backend.py b/hail/python/hail/backend/service_backend.py index 66a7823c039..3a82a0df61c 100644 --- a/hail/python/hail/backend/service_backend.py +++ b/hail/python/hail/backend/service_backend.py @@ -432,9 +432,7 @@ async def _rpc(self, if 'name' not in batch_attributes: batch_attributes = {**batch_attributes, 'name': self.name_prefix} if self._batch is None: - bb = self.async_bc.create_batch(token=token, attributes=batch_attributes) - else: - bb = await self.async_bc.update_batch(self._batch) + self._batch = self.async_bc.create_batch(token=token, attributes=batch_attributes) resources: Dict[str, Union[str, bool]] = {'preemptible': False} if driver_cores is not None: @@ -450,7 +448,7 @@ async def _rpc(self, if storage_requirement_bytes != 0: resources['storage'] = storage_gib_str - j = bb.create_jvm_job( + j = self._batch.create_jvm_job( jar_spec=self.jar_spec.to_dict(), argv=[ ServiceBackend.DRIVER, @@ -465,7 +463,7 @@ async def _rpc(self, cloudfuse=cloudfuse_config, profile=self.flags['profile'] is not None, ) - self._batch = await bb.submit(disable_progress_bar=True) + await self._batch.submit(disable_progress_bar=True) with timings.step("wait driver"): try: diff --git a/hail/python/hail/methods/qc.py b/hail/python/hail/methods/qc.py index b033eb89e8c..0193e7b175e 100644 --- a/hail/python/hail/methods/qc.py +++ b/hail/python/hail/methods/qc.py @@ -904,7 +904,7 @@ def _service_vep(backend: ServiceBackend, else: vep_typ = vep_config.json_typ - def build_vep_batch(bb: bc.aioclient.BatchBuilder, vep_input_path: str, vep_output_path: str): + def build_vep_batch(b: bc.aioclient.Batch, vep_input_path: str, vep_output_path: str): if csq: local_output_file = '/io/output' vep_command = vep_config.command( @@ -920,15 +920,15 @@ def build_vep_batch(bb: bc.aioclient.BatchBuilder, vep_input_path: str, vep_outp 'VEP_COMMAND': vep_command } env.update(vep_config.env) - bb.create_job(vep_config.image, - vep_config.batch_run_csq_header_command, - attributes={'name': 'csq-header'}, - resources={'cpu': '1', 'memory': 'standard'}, - cloudfuse=[(vep_config.data_bucket, vep_config.data_mount, True)], - output_files=[(local_output_file, f'{vep_output_path}/csq-header')], - regions=vep_config.regions, - requester_pays_project=requester_pays_project, - env=env) + b.create_job(vep_config.image, + vep_config.batch_run_csq_header_command, + attributes={'name': 'csq-header'}, + resources={'cpu': '1', 'memory': 'standard'}, + cloudfuse=[(vep_config.data_bucket, vep_config.data_mount, True)], + output_files=[(local_output_file, f'{vep_output_path}/csq-header')], + regions=vep_config.regions, + requester_pays_project=requester_pays_project, + env=env) for f in hl.hadoop_ls(vep_input_path): path = f['path'] @@ -960,25 +960,25 @@ def build_vep_batch(bb: bc.aioclient.BatchBuilder, vep_input_path: str, vep_outp } env.update(vep_config.env) - bb.create_job(vep_config.image, - vep_config.batch_run_command, - attributes={'name': f'vep-{part_id}'}, - resources={'cpu': '1', 'memory': 'standard'}, - input_files=[(path, local_input_file)], - output_files=[(local_output_file, f'{vep_output_path}/annotations/{part_name}.tsv.gz')], - cloudfuse=[(vep_config.data_bucket, vep_config.data_mount, True)], - regions=vep_config.regions, - requester_pays_project=requester_pays_project, - env=env) + b.create_job(vep_config.image, + vep_config.batch_run_command, + attributes={'name': f'vep-{part_id}'}, + resources={'cpu': '1', 'memory': 'standard'}, + input_files=[(path, local_input_file)], + output_files=[(local_output_file, f'{vep_output_path}/annotations/{part_name}.tsv.gz')], + cloudfuse=[(vep_config.data_bucket, vep_config.data_mount, True)], + regions=vep_config.regions, + requester_pays_project=requester_pays_project, + env=env) hl.export_vcf(ht, temp_input_directory, parallel='header_per_shard') starting_job_id = async_to_blocking(backend._batch.status())['n_jobs'] + 1 - bb = backend.bc.update_batch(backend._batch.id) - build_vep_batch(bb, temp_input_directory, temp_output_directory) + b = bc.client.Batch(backend._batch) + build_vep_batch(b, temp_input_directory, temp_output_directory) - b = bb.submit(disable_progress_bar=True) + b.submit(disable_progress_bar=True) try: status = b.wait(description='vep(...)', diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index ce066f00a9f..334e4c1bad4 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -588,11 +588,11 @@ async def _async_run(self, attributes['name'] = batch.name if batch._batch_handle is None: - bc_batch_builder = self._batch_client.create_batch( + batch._batch_handle = self._batch_client.create_batch( attributes=attributes, callback=callback, token=token, cancel_after_n_failures=batch._cancel_after_n_failures ) - else: - bc_batch_builder = self._batch_client.update_batch(batch._batch_handle) + + batch_handle = batch._batch_handle n_jobs_submitted = 0 used_remote_tmpdir = False @@ -637,9 +637,9 @@ def symlink_input_resource_group(r): if dry_run: commands.append(' '.join(shq(x) for x in write_cmd)) else: - j = bc_batch_builder.create_job(image=HAIL_GENETICS_HAILTOP_IMAGE, - command=write_cmd, - attributes={'name': 'write_external_inputs'}) + j = batch._batch_handle.create_job(image=HAIL_GENETICS_HAILTOP_IMAGE, + command=write_cmd, + attributes={'name': 'write_external_inputs'}) jobs_to_command[j] = ' '.join(shq(x) for x in write_cmd) n_jobs_submitted += 1 @@ -736,22 +736,22 @@ async def compile_job(job): env = {**job._env, 'BATCH_TMPDIR': local_tmpdir} - j = bc_batch_builder.create_job(image=image, - command=[job._shell if job._shell else DEFAULT_SHELL, '-c', cmd], - parents=parents, - attributes=attributes, - resources=resources, - input_files=inputs if len(inputs) > 0 else None, - output_files=outputs if len(outputs) > 0 else None, - always_run=job._always_run, - timeout=job._timeout, - cloudfuse=job._cloudfuse if len(job._cloudfuse) > 0 else None, - env=env, - requester_pays_project=batch.requester_pays_project, - mount_tokens=True, - user_code=user_code, - regions=job._regions, - always_copy_output=job._always_copy_output) + j = batch_handle.create_job(image=image, + command=[job._shell if job._shell else DEFAULT_SHELL, '-c', cmd], + parents=parents, + attributes=attributes, + resources=resources, + input_files=inputs if len(inputs) > 0 else None, + output_files=outputs if len(outputs) > 0 else None, + always_run=job._always_run, + timeout=job._timeout, + cloudfuse=job._cloudfuse if len(job._cloudfuse) > 0 else None, + env=env, + requester_pays_project=batch.requester_pays_project, + mount_tokens=True, + user_code=user_code, + regions=job._regions, + always_copy_output=job._always_copy_output) n_jobs_submitted += 1 @@ -764,7 +764,7 @@ async def compile_job(job): if delete_scratch_on_exit and used_remote_tmpdir: parents = list(jobs_to_command.keys()) - j = bc_batch_builder.create_job( + j = batch_handle.create_job( image=HAIL_GENETICS_HAILTOP_IMAGE, command=['python3', '-m', 'hailtop.aiotools.delete', batch_remote_tmpdir], parents=parents, @@ -777,12 +777,9 @@ async def compile_job(job): print(f'Built DAG with {n_jobs_submitted} jobs in {round(time.time() - build_dag_start, 3)} seconds.') submit_batch_start = time.time() - batch_handle = bc_batch_builder.submit(disable_progress_bar=disable_progress_bar) + batch_handle.submit(disable_progress_bar=disable_progress_bar) - if batch._batch_handle is None: - batch._batch_handle = batch_handle - else: - assert batch._batch_handle == batch_handle + batch_id = batch_handle.id for job in batch._unsubmitted_jobs: job._submitted = True @@ -790,23 +787,23 @@ async def compile_job(job): jobs_to_command = {j.id: cmd for j, cmd in jobs_to_command.items()} if verbose: - print(f'Submitted batch {batch_handle.id} with {n_jobs_submitted} jobs in {round(time.time() - submit_batch_start, 3)} seconds:') + print(f'Submitted batch {batch_id} with {n_jobs_submitted} jobs in {round(time.time() - submit_batch_start, 3)} seconds:') for jid, cmd in jobs_to_command.items(): print(f'{jid}: {cmd}') print('') deploy_config = get_deploy_config() - url = deploy_config.external_url('batch', f'/batches/{batch_handle.id}') + url = deploy_config.external_url('batch', f'/batches/{batch_id}') if open: webbrowser.open(url) if wait and len(unsubmitted_jobs) > 0: if verbose: - print(f'Waiting for batch {batch_handle.id}...') + print(f'Waiting for batch {batch_id}...') starting_job_id = min(j._client_job.job_id for j in unsubmitted_jobs) await asyncio.sleep(0.6) # it is not possible for the batch to be finished in less than 600ms status = await batch_handle._async_batch.wait(disable_progress_bar=disable_progress_bar, starting_job=starting_job_id) - print(f'batch {batch_handle.id} complete: {status["state"]}') + print(f'batch {batch_id} complete: {status["state"]}') batch._python_function_defs.clear() batch._python_function_files.clear() diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index e8191c1e1c9..8c0966ff795 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -157,9 +157,9 @@ def _get_duration(container_status): return sum(durations) @staticmethod - def unsubmitted_job(batch_builder, job_id): - assert isinstance(batch_builder, BatchBuilder) - _job = UnsubmittedJob(batch_builder, job_id) + def unsubmitted_job(batch, job_id): + assert isinstance(batch, Batch) + _job = UnsubmittedJob(batch, job_id) return Job(_job) @staticmethod @@ -234,11 +234,11 @@ async def attempts(self): class UnsubmittedJob: - def _submit(self, batch, update_start_job_id): - return SubmittedJob(batch, self._job_id + update_start_job_id - 1) + def _submit(self, update_start_job_id: int): + return SubmittedJob(self._batch, self._job_id + update_start_job_id - 1) - def __init__(self, batch_builder, job_id): - self._batch_builder = batch_builder + def __init__(self, batch: 'Batch', job_id: int): + self._batch = batch self._job_id = job_id @property @@ -351,31 +351,69 @@ async def attempts(self): class BatchSubmissionInfo: - def __init__(self, used_fast_create: Optional[bool] = None, used_fast_update: Optional[Dict[int, bool]] = None): - self.used_fast_create = used_fast_create - self.used_fast_update = used_fast_update or {} + def __init__(self, used_fast_path: Optional[bool] = None): + self.used_fast_path = used_fast_path + + +class BatchNotSubmittedError(Exception): + pass + + +class BatchAlreadyCreatedError(Exception): + pass class Batch: def __init__(self, client: 'BatchClient', - id: int, - attributes: Optional[Dict[str, str]], - token: str, + id: Optional[int], *, - last_known_status: Optional[Dict[str, Any]] = None, - submission_info: Optional[BatchSubmissionInfo] = None): + attributes: Optional[Dict[str, str]] = None, + callback: Optional[str] = None, + token: Optional[str] = None, + cancel_after_n_failures: Optional[int] = None, + last_known_status: Optional[Dict[str, Any]] = None): self._client = client - self.id: int = id + self._id = id self.attributes: Dict[str, str] = attributes or {} + self._callback = callback + + if token is None: + token = secrets.token_urlsafe(32) self.token = token + + self._cancel_after_n_failures = cancel_after_n_failures + self._submission_info = BatchSubmissionInfo() self._last_known_status = last_known_status - self.submission_info = submission_info or BatchSubmissionInfo() + + self._job_idx = 0 + self._job_specs: List[Dict[str, Any]] = [] + self._jobs: List[Job] = [] + + def _raise_if_not_created(self): + if not self.is_created: + raise BatchNotSubmittedError + + def _raise_if_created(self): + if self.is_created: + raise BatchAlreadyCreatedError + + @property + def id(self) -> int: + self._raise_if_not_created() + assert self._id + return self._id + + @property + def is_created(self): + return self._id is not None async def cancel(self): + self._raise_if_not_created() await self._client._patch(f'/api/v1alpha/batches/{self.id}/cancel') async def jobs(self, q: Optional[str] = None, version: Optional[int] = None): + self._raise_if_not_created() if version is None: version = 1 last_job_id = None @@ -394,9 +432,11 @@ async def jobs(self, q: Optional[str] = None, version: Optional[int] = None): break async def get_job(self, job_id: int) -> Job: + self._raise_if_not_created() return await self._client.get_job(self.id, job_id) async def get_job_log(self, job_id: int) -> Optional[Dict[str, Any]]: + self._raise_if_not_created() return await self._client.get_job_log(self.id, job_id) # { @@ -421,6 +461,7 @@ async def get_job_log(self, job_id: int) -> Optional[Dict[str, Any]]: # cost: float # } async def status(self) -> Dict[str, Any]: + self._raise_if_not_created() resp = await self._client._get(f'/api/v1alpha/batches/{self.id}') json_status = await resp.json() assert isinstance(json_status, dict), json_status @@ -428,6 +469,7 @@ async def status(self) -> Dict[str, Any]: return self._last_known_status async def last_known_status(self) -> Dict[str, Any]: + self._raise_if_not_created() if self._last_known_status is None: return await self.status() # updates _last_known_status return self._last_known_status @@ -438,6 +480,7 @@ async def _wait(self, disable_progress_bar: bool, starting_job: int ) -> Dict[str, Any]: + self._raise_if_not_created() deploy_config = get_deploy_config() url = deploy_config.external_url('batch', f'/batches/{self.id}') i = 0 @@ -468,6 +511,7 @@ async def wait(self, progress: Optional[BatchProgressBar] = None, starting_job: int = 1, ) -> Dict[str, Any]: + self._raise_if_not_created() if description: description += ': ' if progress is not None: @@ -476,6 +520,7 @@ async def wait(self, return await self._wait(description, progress2, disable_progress_bar, starting_job) async def debug_info(self): + self._raise_if_not_created() batch_status = await self.status() jobs = [] async for j_status in self.jobs(): @@ -485,39 +530,13 @@ async def debug_info(self): return {'status': batch_status, 'jobs': jobs} async def delete(self): + self._raise_if_not_created() try: await self._client._delete(f'/api/v1alpha/batches/{self.id}') except httpx.ClientResponseError as err: if err.code != 404: raise - -class BatchBuilder: - def __init__(self, - client: 'BatchClient', - *, - attributes: Optional[Dict[str, str]] = None, - callback: Optional[str] = None, - token: Optional[str] = None, - cancel_after_n_failures: Optional[int] = None, - batch: Optional[Batch] = None - ): - self._client = client - self._job_idx = 0 - self._job_specs: List[Dict[str, Any]] = [] - self._jobs: List[Job] = [] - self._batch = batch - self.attributes = attributes - self.callback = callback - - if token is None: - token = secrets.token_urlsafe(32) - self.token: str = token - - self._update_id: Optional[int] = None - - self._cancel_after_n_failures = cancel_after_n_failures - def create_job(self, image: str, command: List[str], **kwargs): return self._create_job( {'command': command, 'image': image, 'type': 'docker'}, **kwargs @@ -562,7 +581,7 @@ def _create_job(self, for parent in parents: job = parent._job if isinstance(job, UnsubmittedJob): - if job._batch_builder != self: + if job._batch != self: foreign_batches.append(job) elif not 0 < job._job_id < self._job_idx: invalid_job_ids.append(job) @@ -570,7 +589,7 @@ def _create_job(self, in_update_parent_ids.append(job._job_id) else: assert isinstance(job, SubmittedJob) - if self._batch is None or job._batch != self._batch: + if not self.is_created or job._batch.id != self.id: foreign_batches.append(job) else: absolute_parent_ids.append(job.job_id) @@ -641,8 +660,8 @@ def _create_job(self, self._jobs.append(j) return j - async def _create_fast(self, byte_job_specs: List[bytes], n_jobs: int, job_progress_task: BatchProgressBarTask) -> Batch: - assert not self._batch + async def _create_fast(self, byte_job_specs: List[bytes], n_jobs: int, job_progress_task: BatchProgressBarTask): + self._raise_if_created() assert n_jobs == len(self._job_specs) b = bytearray() b.extend(b'{"bunch":') @@ -661,14 +680,12 @@ async def _create_fast(self, byte_job_specs: List[bytes], n_jobs: int, job_progr ) batch_json = await resp.json() job_progress_task.update(n_jobs) - return Batch(self._client, - batch_json['id'], - self.attributes, - self.token, - submission_info=BatchSubmissionInfo(True)) + + self._id = batch_json['id'] + self._submission_info = BatchSubmissionInfo(used_fast_path=True) async def _update_fast(self, byte_job_specs: List[bytes], n_jobs: int, job_progress_task: BatchProgressBarTask) -> int: - assert self._batch + self._raise_if_not_created() assert n_jobs == len(self._job_specs) b = bytearray() b.extend(b'{"bunch":') @@ -682,11 +699,12 @@ async def _update_fast(self, byte_job_specs: List[bytes], n_jobs: int, job_progr b.extend(json.dumps(self._update_spec()).encode('utf-8')) b.append(ord('}')) resp = await self._client._post( - f'/api/v1alpha/batches/{self._batch.id}/update-fast', + f'/api/v1alpha/batches/{self.id}/update-fast', data=aiohttp.BytesPayload(b, content_type='application/json', encoding='utf-8'), ) update_json = await resp.json() job_progress_task.update(n_jobs) + self._submission_info = BatchSubmissionInfo(used_fast_path=True) return int(update_json['start_job_id']) def _create_bunches(self, @@ -723,7 +741,8 @@ def _create_bunches(self, return (byte_specs_bunches, bunch_sizes) - async def _submit_jobs(self, batch_id: int, update_id: int, byte_job_specs: List[bytes], n_jobs: int, progress_task: BatchProgressBarTask): + async def _submit_jobs(self, update_id: int, byte_job_specs: List[bytes], n_jobs: int, progress_task: BatchProgressBarTask): + self._raise_if_not_created() assert len(byte_job_specs) > 0, byte_job_specs b = bytearray() @@ -740,7 +759,7 @@ async def _submit_jobs(self, batch_id: int, update_id: int, byte_job_specs: List b.append(ord(']')) await self._client._post( - f'/api/v1alpha/batches/{batch_id}/updates/{update_id}/jobs/create', + f'/api/v1alpha/batches/{self.id}/updates/{update_id}/jobs/create', data=aiohttp.BytesPayload(b, content_type='application/json', encoding='utf-8'), ) progress_task.update(n_jobs) @@ -750,42 +769,45 @@ def _batch_spec(self): batch_spec = {'billing_project': self._client.billing_project, 'n_jobs': n_jobs, 'token': self.token} if self.attributes: batch_spec['attributes'] = self.attributes - if self.callback: - batch_spec['callback'] = self.callback + if self._callback: + batch_spec['callback'] = self._callback if self._cancel_after_n_failures is not None: batch_spec['cancel_after_n_failures'] = self._cancel_after_n_failures return batch_spec - async def _open_batch(self) -> Batch: + async def _open_batch(self) -> Optional[int]: + self._raise_if_created() batch_spec = self._batch_spec() batch_json = await (await self._client._post('/api/v1alpha/batches/create', json=batch_spec)).json() - self._update_id = batch_json['update_id'] - return Batch(self._client, - batch_json['id'], - self.attributes, - self.token, - submission_info=BatchSubmissionInfo(False)) + self._id = batch_json['id'] + update_id = batch_json['update_id'] + if update_id is None: + assert batch_spec['n_jobs'] == 0 + return update_id def _update_spec(self) -> dict: update_token = secrets.token_urlsafe(32) return {'n_jobs': len(self._jobs), 'token': update_token} - async def _create_update(self, batch_id: int) -> int: + async def _create_update(self) -> int: + self._raise_if_not_created() update_spec = self._update_spec() - update_json = await (await self._client._post(f'/api/v1alpha/batches/{batch_id}/updates/create', json=update_spec)).json() + update_json = await (await self._client._post(f'/api/v1alpha/batches/{self.id}/updates/create', json=update_spec)).json() return int(update_json['update_id']) - async def _commit_update(self, batch_id: int, update_id: int) -> int: - commit_json = await (await self._client._patch(f'/api/v1alpha/batches/{batch_id}/updates/{update_id}/commit')).json() + async def _commit_update(self, update_id: int) -> int: + self._raise_if_not_created() + commit_json = await (await self._client._patch(f'/api/v1alpha/batches/{self.id}/updates/{update_id}/commit')).json() return int(commit_json['start_job_id']) async def _submit_job_bunches(self, + update_id: int, byte_job_specs_bunches: List[List[bytes]], bunch_sizes: List[int], progress_task: BatchProgressBarTask): - assert self._batch + self._raise_if_not_created() await bounded_gather( - *[functools.partial(self._submit_jobs, self._batch.id, self._update_id, bunch, size, progress_task) + *[functools.partial(self._submit_jobs, update_id, bunch, size, progress_task) for bunch, size in zip(byte_job_specs_bunches, bunch_sizes) ], parallelism=6, @@ -805,22 +827,22 @@ async def _submit(self, progress.progress.disable = True with progress.with_task('submit job bunches', total=n_jobs, disable=disable_progress_bar) as job_progress_task: - if self._batch is None: + if not self.is_created: if n_job_bunches == 0: - self._batch = await self._open_batch() - log.info(f'created batch {self._batch.id}') + await self._open_batch() + log.info(f'created batch {self.id}') return None if n_job_bunches == 1: - self._batch = await self._create_fast(byte_job_specs_bunches[0], job_bunch_sizes[0], job_progress_task) + await self._create_fast(byte_job_specs_bunches[0], job_bunch_sizes[0], job_progress_task) start_job_id = 1 else: - self._batch = await self._open_batch() - assert self._update_id is not None - await self._submit_job_bunches(byte_job_specs_bunches, job_bunch_sizes, job_progress_task) - start_job_id = await self._commit_update(self._batch.id, self._update_id) - self._batch.submission_info.used_fast_update[self._update_id] = False + update_id = await self._open_batch() + assert update_id is not None + await self._submit_job_bunches(update_id, byte_job_specs_bunches, job_bunch_sizes, job_progress_task) + start_job_id = await self._commit_update(update_id) + self._submission_info = BatchSubmissionInfo(used_fast_path=False) assert start_job_id == 1 - log.info(f'created batch {self._batch.id}') + log.info(f'created batch {self.id}') else: if n_job_bunches == 0: log.warning('Tried to submit an update with 0 jobs. Doing nothing.') @@ -828,11 +850,11 @@ async def _submit(self, if n_job_bunches == 1: start_job_id = await self._update_fast(byte_job_specs_bunches[0], job_bunch_sizes[0], job_progress_task) else: - self._update_id = await self._create_update(self._batch.id) - await self._submit_job_bunches(byte_job_specs_bunches, job_bunch_sizes, job_progress_task) - start_job_id = await self._commit_update(self._batch.id, self._update_id) - self._batch.submission_info.used_fast_update[self._update_id] = False - log.info(f'updated batch {self._batch.id}') + update_id = await self._create_update() + await self._submit_job_bunches(update_id, byte_job_specs_bunches, job_bunch_sizes, job_progress_task) + start_job_id = await self._commit_update(update_id) + self._submission_info = BatchSubmissionInfo(used_fast_path=False) + log.info(f'updated batch {self.id}') return start_job_id MAX_BUNCH_BYTESIZE = 1024 * 1024 @@ -844,7 +866,7 @@ async def submit(self, disable_progress_bar: bool = False, *, progress: Optional[BatchProgressBar] = None - ) -> Batch: + ): assert max_bunch_bytesize > 0 assert max_bunch_size > 0 @@ -854,18 +876,16 @@ async def submit(self, with BatchProgressBar(disable=disable_progress_bar) as progress2: start_job_id = await self._submit(max_bunch_bytesize, max_bunch_size, disable_progress_bar, 100, progress2) - assert self._batch is not None + assert self.is_created for j in self._jobs: assert start_job_id is not None - j._job = j._job._submit(self._batch, start_job_id) + j._job = j._job._submit(start_job_id) self._job_specs = [] self._jobs = [] self._job_idx = 0 - return self._batch - class HailExplicitTokenCredentials(CloudCredentials): def __init__(self, token: str): @@ -977,18 +997,18 @@ async def get_batch(self, id) -> Batch: attributes = b.get('attributes') assert attributes is None or isinstance(attributes, dict), attributes return Batch(self, - b['id'], + id=b['id'], attributes=attributes, token=b['token'], last_known_status=b) - def create_batch(self, attributes=None, callback=None, token=None, cancel_after_n_failures=None) -> BatchBuilder: - return BatchBuilder(self, attributes=attributes, callback=callback, token=token, cancel_after_n_failures=cancel_after_n_failures) - - async def update_batch(self, batch: Union[int, Batch]) -> BatchBuilder: - if isinstance(batch, Batch): - return BatchBuilder(self, batch=batch) - return BatchBuilder(self, batch=await self.get_batch(batch)) + def create_batch(self, attributes=None, callback=None, token=None, cancel_after_n_failures=None) -> Batch: + return Batch(self, + id=None, + attributes=attributes, + callback=callback, + token=token, + cancel_after_n_failures=cancel_after_n_failures) async def get_billing_project(self, billing_project): bp_resp = await self._get(f'/api/v1alpha/billing_projects/{billing_project}') diff --git a/hail/python/hailtop/batch_client/client.py b/hail/python/hailtop/batch_client/client.py index 61a13a4c329..d1fec0132a5 100644 --- a/hail/python/hailtop/batch_client/client.py +++ b/hail/python/hailtop/batch_client/client.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional from hailtop.utils import async_to_blocking, ait_to_blocking from ..config import DeployConfig @@ -104,14 +104,18 @@ def attempts(self): class Batch: - @classmethod - def from_async_batch(cls, batch: aioclient.Batch): - b = object.__new__(cls) - b._async_batch = batch - return b + @staticmethod + def _open_batch(client: 'BatchClient', token: Optional[str] = None) -> 'Batch': + async_batch = client.create_batch(token=token)._async_batch + async_to_blocking(async_batch._open_batch()) + return Batch(async_batch) - def __init__(self, client, id, attributes, token): - self._async_batch: aioclient.Batch = aioclient.Batch(client, id, attributes, token) + def __init__(self, async_batch: aioclient.Batch): + self._async_batch = async_batch + + @property + def is_created(self) -> bool: + return self._async_batch.is_created @property def id(self) -> int: @@ -126,8 +130,8 @@ def token(self): return self._async_batch.token @property - def submission_info(self): - return self._async_batch.submission_info + def _submission_info(self): + return self._async_batch._submission_info def cancel(self): async_to_blocking(self._async_batch.cancel()) @@ -178,34 +182,6 @@ def debug_info(self): def delete(self): async_to_blocking(self._async_batch.delete()) - -class BatchBuilder: - @classmethod - def from_async_builder(cls, builder: aioclient.BatchBuilder, batch: Optional[Batch] = None) -> 'BatchBuilder': - b = object.__new__(cls) - b._async_builder = builder - b._batch = batch - return b - - def __init__(self, client, attributes, callback, token: Optional[str] = None, - cancel_after_n_failures: Optional[int] = None, batch: Optional[Batch] = None): - self._async_builder: aioclient.BatchBuilder = aioclient.BatchBuilder( - client, attributes=attributes, callback=callback, token=token, cancel_after_n_failures=cancel_after_n_failures - ) - self._batch = batch - - @property - def attributes(self): - return self._async_builder.attributes - - @property - def callback(self): - return self._async_builder.callback - - @property - def token(self): - return self._async_builder.token - def create_job(self, image, command, @@ -222,7 +198,7 @@ def create_job(self, if parents: parents = [parent._async_job for parent in parents] - async_job = self._async_builder.create_job( + async_job = self._async_batch.create_job( image, command, env=env, port=port, resources=resources, secrets=secrets, service_account=service_account, @@ -239,20 +215,12 @@ def create_jvm_job(self, command, *, profile: bool = False, parents=None, **kwar if parents: parents = [parent._async_job for parent in parents] - async_job = self._async_builder.create_jvm_job(command, profile=profile, parents=parents, **kwargs) + async_job = self._async_batch.create_jvm_job(command, profile=profile, parents=parents, **kwargs) return Job.from_async_job(async_job) - def _open_batch(self) -> Batch: - async_batch = async_to_blocking(self._async_builder._open_batch()) - return Batch.from_async_batch(async_batch) - - def submit(self, *args, **kwargs) -> Batch: - async_batch = async_to_blocking(self._async_builder.submit(*args, **kwargs)) - if self._batch is None: - batch = Batch.from_async_batch(async_batch) - self._batch = batch - return self._batch + def submit(self, *args, **kwargs): + async_to_blocking(self._async_batch.submit(*args, **kwargs)) class BatchClient: @@ -281,7 +249,7 @@ def reset_billing_project(self, billing_project): def list_batches(self, q=None, last_batch_id=None, limit=2**64, version=None): for b in ait_to_blocking(self._async_client.list_batches(q=q, last_batch_id=last_batch_id, limit=limit, version=version)): - yield Batch.from_async_batch(b) + yield Batch(b) def get_job(self, batch_id, job_id): j = async_to_blocking(self._async_client.get_job(batch_id, job_id)) @@ -297,24 +265,19 @@ def get_job_attempts(self, batch_id, job_id): def get_batch(self, id): b = async_to_blocking(self._async_client.get_batch(id)) - return Batch.from_async_batch(b) + return Batch(b) def create_batch(self, attributes=None, callback=None, token=None, cancel_after_n_failures=None - ) -> 'BatchBuilder': - builder = self._async_client.create_batch(attributes=attributes, callback=callback, token=token, - cancel_after_n_failures=cancel_after_n_failures) - return BatchBuilder.from_async_builder(builder) - - def update_batch(self, batch: Union[int, Batch]) -> 'BatchBuilder': - _batch = batch._async_batch if isinstance(batch, Batch) else batch - batch_builder = async_to_blocking(self._async_client.update_batch(_batch)) - if isinstance(batch, Batch): - return BatchBuilder.from_async_builder(batch_builder, batch=batch) - return BatchBuilder.from_async_builder(batch_builder, batch=None) + ) -> 'Batch': + batch = self._async_client.create_batch(attributes=attributes, + callback=callback, + token=token, + cancel_after_n_failures=cancel_after_n_failures) + return Batch(batch) def get_billing_project(self, billing_project): return async_to_blocking(self._async_client.get_billing_project(billing_project)) diff --git a/hail/python/test/hailtop/batch/test_batch.py b/hail/python/test/hailtop/batch/test_batch.py index 503106a1ee0..9f5fc08d166 100644 --- a/hail/python/test/hailtop/batch/test_batch.py +++ b/hail/python/test/hailtop/batch/test_batch.py @@ -1077,7 +1077,7 @@ def test_big_batch_which_uses_slow_path(self): long_str = secrets.token_urlsafe(256 * 1024) j1.command(f'echo "{long_str}" > /dev/null') batch = b.run() - assert not batch.submission_info.used_fast_create + assert not batch._submission_info.used_fast_path batch_status = batch.status() assert batch_status['state'] == 'success', str((batch.debug_info())) From 3de55e026f688fc265f18ee4499ae4d27c7c8383 Mon Sep 17 00:00:00 2001 From: jigold Date: Mon, 21 Aug 2023 17:19:18 -0400 Subject: [PATCH 125/180] [devdocs] Batch System Developer Docs (#13427) I ported what I wrote in the RFC for job groups here and added some additional information about infrastructure. Some of that is TBD. Please let me know if the cancellation description here isn't enough and I'll go dig up all of the discussion from the cancellation RFC. I think this document could definitely be improved, but I wanted to get an MVP out. --- ...ch-design.md => batch-container-design.md} | 0 dev-docs/batch-design.rst | 764 ++++++++++++++++++ 2 files changed, 764 insertions(+) rename dev-docs/{batch-design.md => batch-container-design.md} (100%) create mode 100644 dev-docs/batch-design.rst diff --git a/dev-docs/batch-design.md b/dev-docs/batch-container-design.md similarity index 100% rename from dev-docs/batch-design.md rename to dev-docs/batch-container-design.md diff --git a/dev-docs/batch-design.rst b/dev-docs/batch-design.rst new file mode 100644 index 00000000000..0b0ea2005e6 --- /dev/null +++ b/dev-docs/batch-design.rst @@ -0,0 +1,764 @@ +============ +Batch Design +============ + +.. sectnum:: +.. contents:: + +******** +Overview +******** + +Hail Batch is a multi-tenant batch job processing system. The Hail +team maintains deployments in GCP and Azure. There are also a few +deployments outside of the control of the Hail team as well as alpha +support in Terra. Hail Batch has two main use cases: (1) a batch job +processing system that executes arbitrary bash or Python code in +containerized environments that are generated using a Python client +library that handles file localization and job dependencies in a +user-friendly manner (hailtop.batch) and (2) as the backend for +running Hail Query on Batch (QoB) inside containers running Hail team +approved JVM byte code. + +Typical users of hailtop.batch are looking to execute code for a +stand-alone scientific tool that can be run massively in parallel such +as across samples in a dataset and regions in a genome. Their +workloads usually consist of a single scatter layer with no +dependencies between jobs with sizes on the order of 100s to 100Ks of +jobs. The largest batch that has been processed by the Hail Batch +system is ~16 million jobs. Likewise, QoB consists of a single, +nonpreemptible driver job and subsequent sets of updates of jobs to +the directed acyclic graph (DAG) for subsequent stages of worker +jobs. There is a single job per partition within a stage. The number +of jobs within a stage can be on the order of 100K jobs. + + +**************************** +How the Current System Works +**************************** + +The Batch system is a set of services and infrastructure components +that work in concert to allow users to submit requests describing +workloads or sets of jobs to run and then executes the jobs on a set +of worker VMs. There is both a UI and a REST API for interacting with +Batch. The infrastructure required for a working Hail Batch system +consists of a Kubernetes cluster, a container registry, blob storage, +a MySQL database, and virtual machines (VMs). In this document, we describe +the purpose of each infrastructural component and how they all work in +concert to create a working Batch system. We also expand on how both +of the Batch Python web servers are implemented in detail such as +database representations, how cancellation works, how the autoscaler +works, and how billing works. Lastly, we describe what happens on the +worker VMs. + + + +Infrastructure +============== + +The Batch system consists of the following Kubernetes +services and cloud infrastructure components: + +- Kubernetes Services + - Gateway (gateway) + - Internal Gateway (internal-gateway) + - Auth (auth) + - Auth Driver (auth-driver) + - Batch Front End (batch) + - Batch Driver (batch-driver) +- Worker VMs +- MySQL Database +- Cloud Storage +- Container Registry + + +Kubernetes Services +------------------- + + +Gateway +^^^^^^^ + +Gateway is a Kubernetes service and associated cloud-provider-managed +external load balancer. It is associated with a statically +known external IP Address. This is the entry point in which external +users send requests to the Batch system such as submitting batches and +getting information on their jobs. There is a an Envoy server behind +the load balancer that forwards requests to the appropriate service. + + +Internal Gateway +^^^^^^^^^^^^^^^^ + +Internal Gateway is a Kubernetes service and associated cloud-provider-managed +internal load balancer. Unlike the Gateway, the Internal +Gateway is associated with a statically known **internal** IP address +that is only accessible from virtual machines within our private +network. This endpoint is how Batch worker VMs are able to talk to the +Batch Driver Kubernetes Service directly without going through the public +internet. + + +Auth / Auth-Driver +^^^^^^^^^^^^^^^^^^ + +The Auth Kubernetes service is responsible for creating new users, +logging in existing users, authenticating requests from logged in +users, verifying developer status for accessing protected services +like a batch deployment in a developer namespace. We will soon be +changing how authentication / authorization is implemented. Currently, +for REST API requests, a user provides an authorization bearer header +with a Hail-issued token. This token is generated when users login and +has a default expiration date for 30 days. UI web requests have an +associated cookie that includes the token. The Auth Driver service is +responsible for creating new user resources such as service accounts, +secondary Kubernetes namespaces for developers, Kubernetes secrets +that store the user's active Hail authorization token and their Google +service account or Azure service principal certificates, which allows +users to access their resources required to execute jobs such as +Docker images and data stored in Google Cloud Storage or Azure Blob +Storage. When a user is deleted, their corresponding resources are +deleted as well. + + +Batch Front End +^^^^^^^^^^^^^^^ + +The Batch Front End is a Kubernetes service responsible for handling +user requests such as creating batches, updating batches, and viewing +job logs. How the Batch Front End Python service works is described in +more detail later in this document. When users submit requests to +authenticated endpoints (everything except for /healthcheck), the +Batch service sends a request to the Auth service to see if the token +submitted in the request is valid and in exchange get information +about the user. The Batch Front End can also send requests to the +Batch Driver notifying the driver that a batch has been created or +needs to be cancelled ("push notification"). The application is stateless +and 3 copies are running simultaneously. The Front End +extensively updates and queries the MySQL database to obtain the +information necessary to fulfill user requests. It also writes job +specs to cloud storage for use downstream by the worker VMs. + + +Batch Driver +^^^^^^^^^^^^ + +The Batch Driver is a Kubernetes service responsible for provisioning +worker VMs in response to demand, scheduling jobs on free worker VMs, +and cancelling jobs that no longer should be run. The Driver is +stateless, but only 1 copy can be running at a single time. This is +because our current strategy for knowing how many free cores per VM +are available requires a single process to accurately update the +number of free cores when we schedule a job on a VM. The Driver +communicates with worker VMs when it schedules or unschedules +jobs. The worker VMs then communicate back to the Driver when a worker +is ready to activate itself and start receiving work, notifying a job +has been completed, and deactivating itself when it is idle. The Batch +Driver has a second container inside the pod that is an Envoy server +responsible for maintaining TLS handshakes so as to reduce the CPU +load on the actual Python web server. + + +Worker VMs +---------- + +Worker VMs are virtual machines that are created outside of the +Kubernetes cluster. They share a network with the Kubernetes VMs, but +not with the Kubernetes pods. They are created with a default service +account that has permissions to read and write files to cloud storage +such as job specs and job logs as well as delete VMs (so it can delete +itself). Virtual machines are created with a preconfigured boot disk +image that has Docker preinstalled. Startup scripts then initialize +the worker VM, download the worker server application image from a +container registry, and then create the worker Docker container. Once +the worker container is running, it notifies the Batch Driver that it +is active and starts executing jobs. + + +MySQL Database +-------------- + +All Batch and Auth state is stored in a cloud-provider managed MySQL +database. We use SSL certificates to secure communication between +Kubernetes services and the database. Worker VMs cannot talk directly +to the database. + + +Cloud Storage +------------- + +Users store the data they want to compute on in Cloud Storage (Google +Cloud Storage or Azure Blob Storage). All Batch created files such as +user job specs, job log files, job status files, and job resource +usage monitoring files are stored in cloud storage. + + +Container Registry +------------------ + +Container images used to execute user jobs as well as the images used +in our Kubernetes services are stored in a cloud provider managed +Container Registry (Google Artifact Registry and Azure Container +Registry). + + +Terraform +--------- + +TBD. + + +Bootstrapping +------------- + +TBD. + + +Application Details +=================== + +Batch Lifecycle +--------------- + +1. A user submits a request to the Batch front end service to create a + batch along with job specifications. +2. The Batch front end service records the batch and job information + into a MySQL database and writes the job specifications to cloud + storage. +3. The Batch driver notices that there is work available either + through a push request from the Batch front end or by polling the + state in the MySQL database and spins up worker VMs. +4. The worker VMs startup and notify the Batch driver they are active + and have resources to run jobs. +5. The Batch driver schedules jobs to run on the active workers. +6. The worker VM downloads the job specification from cloud storage, + downloads any input files the job needs from cloud storage, creates + a container for the job to execute in, executes the code inside the + container, uploads any logs and output files that have been + generated, and then notifies the Batch driver that the job has + completed. +7. Once all jobs have completed, the batch is set to complete in the + database. Any callbacks that have been specified on batch + completion are called. +8. Meanwhile, the user can find the status of their batch through the + UI or using a Python client library to get the batch status, cancel + the batch, list the jobs in the batch and their statuses, and wait + for the batch or an individual job to complete. The implementation + of the wait operation is by continuously polling the Batch Front + End until the batch state is "complete". + + +Data Model +---------- + +The core concepts in the Batch data model are billing projects, +batches, jobs, updates, attempts, and resources. + +A **billing project** is a mechanism for cost accounting, cost control, and +enabling the ability to share information about batches and jobs +across users. Each billing project has a list of authorized users and +a billing limit. Any users in the billing project can view information +about batches created in that billing project. Developers can +add/delete users in a billing project and modify billing limits. Right +now, these operations are manually done after a Batch user submits a +formal request to the Hail team. Note that the Hail billing project is +different than a GCP billing project. + +A **batch** is a set of **jobs**. Each batch is associated with a +single billing project. A batch also consists of a set of +**updates**. Each update contains a distinct set of jobs. Updates are +distinct submissions of jobs to an existing batch in the system. They +are used as a way to add jobs to a batch. A batch is always created +with 0 updates and 0 total jobs. To add jobs to a batch, an update +must be created with an additional API call and the number of jobs in +the update must be known at the time of the API call. The reason for +this is because an update reserves a block of job IDs in order to +allow multiple updates to a batch to be submitted simultaneously +without the need for locking as well as for jobs within the update to +be able to reference each other before the actual job IDs are +known. Once all of the jobs for a given batch update have been +submitted, the update must be committed in order for the jobs to be +visible in the UI and processed by the batch driver. + +A job can have **attempts**. An attempt is an individual execution +attempt of a job running on a worker VM. There can be multiple +attempts if a job is preempted. If a job is cancelled before it has a +chance to run, it will have zero attempts. An attempt has the +**instance** name that it ran on, the start time, and the end +time. The end time must always be greater than the start time. All +billing tracking is done at the level of an attempt as different +attempts for the same job can have different resource pricing if the +VM configurations are different (4 core worker vs 16 core worker). + +Billing is tracked by **resources**. A resource is a product (example: +preemptible n1-standard-16 VM in us-central1) combined with a version +tag. Each resource has a rate that is used to compute cost when +multiplied by the usage of the resource. Resource rates are in units +that are dependent on the type of resource. For example, VM rates are +denominated in USD per core-hour. Each attempt has a set of resources +associated with it along with their usage in a resource-dependent set +of units. For example, a 1 core job has a usage value of 1000 (this +value is in mCPU). To compute the aggregate cost of a job, we sum up +all of the usages multiplied by the rates and then multiplied by the +duration the attempt has been running. + + +State Diagram +------------- + +A job can be in one of the following states: + +- Pending: 1+ parent jobs have not completed yet +- Ready: No pending parent jobs. +- Creating: Creating a VM for job private jobs. +- Running: Job is running on a worker VM. +- Success: Job completed successfully. +- Failed: Job failed. +- Cancelled: Job was cancelled either by the system, by the user, or + because at least one of its parents failed. +- Error: Job failed due to an error in creating the container, an out + of memory error, or a Batch bug (ex: user tries to use a nonexistent + image). + +The allowed state transitions are: Pending -> Ready Ready -> +{Creating, Running, Cancelled} Creating -> {Running, Cancelled} +Running -> {Success, Failed, Error, Cancelled} + +A job's initial state depends on the states of its parent jobs. If it +has no parent jobs, its initial state is Ready. + +A batch can be in one of the following states: + +- completed: All jobs are in a completed state {Success, Failed, + Error, Cancelled} +- running: At least one job is in a non-completed state {Pending, + Ready, Running} + +The batch and job states are critical for database performance and +must be indexed appropriately. + + +Batch Front End +--------------- + +The Batch Front End service (batch) is a stateless web service that +handles requests from the user. The front end exposes a REST API +interface for handling user requests such as creating a batch, +updating a batch, creating jobs in a batch, getting the status of a +batch, getting the status of a job, listing all the batches in a +billing project, and listing all of the jobs in a batch. There are +usually 3 copies of the batch front end service running at a given +time to be able to handle requests to create jobs in a batch with a +high degree of parallelism. This is necessary for batches with more +than a million jobs. + + +Flow for Creating and Updating Batches +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following flow is used to create a new batch or update an existing +batch with a set of job specifications: + +1. The client library submits a POST request to create a new batch at + ``/api/v1alpha/batches/create``. A new entry for the batch is + inserted into the database along with any associated tables. For + example, if a user provides attributes (labels) on the batch, that + information is populated into the ``batch_attributes`` table. A new + update is also created for that batch if the request contains a + reservation with more than 1 job. The new batch id and possibly the + new update id are returned to the client. + +2. The client library submits job specifications in 6-way parallelism + in groups of jobs, called bunches, for the newly created batch update as a POST + request to + ``/api/v1alpha/batches/{batch_id}/updates/{update_id}/jobs/create``. The + front end service creates new entries into the jobs table as well + as associated tables such as the table that stores the attributes + for the job. + +3. The user commits the update by sending a POST request to + ``/api/v1alpha/batches/{batch_id}/updates/{update_id}/commit``. After + this, no additional jobs can be submitted for that update. The + front end service executes a SQL stored procedure in the database + that does some bookkeeping to transition these staged jobs into + jobs the batch driver will be able to process and run. + +The flow for updating an existing batch is almost identical to the one +above except step 1 submits a request to +``/api/v1alpha/batches/{batch_id}/updates/create``. + +There are also two fast paths for creating and updating batches when +all jobs fit in a single HTTP request. At time of writing, our client +code uses this path when there are fewer than 1,024 jobs and the +specifications fit in fewer than 1KiB. at +``/api/v1alpha/batches/{batch_id}/create-fast`` and +``/api/v1alpha/batches/{batch_id}/update-fast``. + + +Listing Batches and Jobs +^^^^^^^^^^^^^^^^^^^^^^^^ + +To find all matching batches and jobs either via the UI or the Python +client library, a user provides a query filtering string as well as an +optional starting ID. The server then sends the next 50 records in +response and it is up to the client to send the next request with the +ID of the last record returned in the subsequent request. + + +Batch Driver +------------ + +The Batch Driver is a Kubernetes service that creates a fleet of +worker VMs in response to user workloads and has mechanisms in place +for sharing resources fairly across users. It also has many background +processes to make sure orphaned resources such as disks and VMs are +cleaned up, billing prices for resources are up to date, and +cancelling batches with more than N failures if specified by the +user. The service can be located on a preemptible machine, but we use +a non-preemptible machine to minimize downtime, especially when the +cluster is large. There can only be one driver service in existence at +any one time. There is an Envoy side car container in the batch driver +pod to handle TLS handshakes to avoid excess CPU usage of the batch +driver. + + +Instance Collections +^^^^^^^^^^^^^^^^^^^^ + +The batch driver maintains two different types of collections of +workers. There are **pools** that are multi-tenant and have a +dedicated worker type that is shared across all jobs. Pools can +support both preemptible and nonpreemptible VMs. Right now, there are +three types of machine types we support that correspond to low memory +(~1GB memory / core), standard (~4GB memory / core), and high memory +(~8GB memory / core) machines. These are correspondingly the +"highcpu", "standard", and "highmem" pools. Each pool has its own +scheduler and autoscaler. In addition, there's a single job private +instance manager that creates a worker VM per job and is used if the +worker requests a specific machine type. This is used commonly for +jobs that require more memory than a 16 core machine can provide. + + +Fair Share +^^^^^^^^^^ + +In order to avoid having one user starve other users from getting +their jobs run, we use the following fair share algorithm. We start +with the user who has the fewest cores running. We then allocate as +many cores as possible that are live in the cluster until we reach the +number of cores the next user has currently running. We then divide up +the remaining cores equally amongst the two users until we reach the +number of cores the next user has running. We repeat until we have +either exhausted all free cores in the cluster or have satisfied all +user resource requests. The query to get the number of ready cores in the fair +share algorithm is fast because we aggregate across a global table +``user_inst_coll_resources`` that has a limited number of rows +maintaining counts of the number of ready cores per instance +collection and user. + + +Autoscaler +^^^^^^^^^^ + +At a high level, the autoscaler is in charge of figuring out how many +worker VMs are required to run all of the jobs that are ready to run +without wasting resources. The simplest autoscaler takes the number of +ready cores total across all users and divides up that amount by the +number of cores per worker to get the number of instances that are +required. It then spins up a configurable number of instances each +time the autoscaler runs to avoid cloud provider API rate limits. This +approach works well for large workloads that have long running +jobs. However, the autoscaler can produce more cores than the +scheduler can keep busy with work. This happens when there are many +jobs with a short execution time. + +Due to differences in resource prices across regions and extra fees +for inter-region data transfer, the autoscaler needs to be aware of +the regions a job can run in when scaling up the cluster in order to +avoid suboptimal cluster utilization or jobs not being able to be +scheduled due to a lack of resources. + +The current autoscaler works by running every 15 seconds and executing +the following operations to determine the optimal number of instances +to spin up per region: + +1. Get the fair share resource allocations for each user across all + regions and figure out the share for each user out of 300 (this + represents number of scheduling opportunities this user gets + relative to other users). +2. For every user, sort the "Ready" jobs by regions the job can run in + and take the first N jobs where N is equal to the user share + computed in (1) multiplied by the autoscaler window, which is + currently set to 2.5 minutes. The logic behind this number is it + takes ~2.5 minutes to spin up a new instance so we only want to + look at a small window at a time to avoid spinning up too many + instances. It also makes this query feasible to set a limit on it + and only look at the head of the job queue. +3. Take the union of the result sets for all of the users in (2) in + fair share order. Do another pass over the result set where we + assign each job a scheduling iteration which represents an estimate + of which iteration of the scheduler that job will be scheduled in + assuming the user's fair share. +4. Sort the result set by user fair share and the scheduling iteration + and the regions that job can run in. Aggregate the free cores by + regions in order in the result set. This becomes the number of free + cores to use when computing the number of required instances and + the possible regions the instance can be spun up in. + + +Scheduler +^^^^^^^^^ + +The scheduler finds the set of jobs to schedule by iterating through +each user in fair share order and then scheduling jobs with a "Ready" +state until the user's fair share allocation has been met. The result +set for each user is sorted by regions so that the scheduler matches +what the autoscaler is trying to provision for. The logic behind +scheduling is not very sophisticated so it is possible to have a job +get stuck if for example it requires 8 cores, but two instances are +live with 4 cores each. + +Once the scheduler has assigned jobs to their respective instances, +the scheduler performs the work necessary to grab any secrets from +Kubernetes, update the job state and add an attempt in the database, +and then communicate with the worker VM to start running the +job. There must be a timeout on this scheduling attempt that is short +(1 second) in order to ensure that a delay in one job doesn't cause +the scheduler to get stuck waiting for that one job to be finished +scheduling. We wait at the end of the scheduling iteration for all +jobs to finish scheduling. If we didn't wait, then we might try and +reschedule the same job multiple times before the original operation +to schedule the job in the database completes. + + +Job State Updates +^^^^^^^^^^^^^^^^^ + +There are three main job state update operations: +- SJ: Schedule Job +- MJS: Mark job started +- MJC: Mark job completed + +SJ is a database operation (stored procedure) that happens on the +driver before the job has been scheduled on the worker VM. In the +stored procedure, we check whether an attempt already exists for this +job. If it does not, we create the attempt and subtract the free cores +from the instance in the database. If it does exist, then we don't do +anything. We check the batch has not been cancelled or completed and +the instance is active before setting the job state to Running. + +MJS is a database operation that is initiated by the worker VM when +the job starts running. The worker sends the start time of the attempt +along with the resources it is using. If the attempt does not exist +yet, we create the attempt and subtract the free cores from the +instance in the database. We then update the job state to Running if +it is not already and not been cancelled or completed already. We then +update the start time of the attempt to that given by the +worker. Lastly, we execute a separate database query that inserts the +appropriate resources for that attempt into the database. + +MJC is a database operation that is initiated by the worker VM when +the job completes. The worker sends the start and end time of the +attempt along with the resources it is using. If the attempt does not +exist yet, we create the attempt and subtract the free cores from the +instance in the database. We then update the job state to the +appropriate completed state if it is not already and not been +cancelled or completed already. We then update the start and end times +of the attempt to that given by the worker. We then find all of the +children of the completed job and subtract the number of pending +parents by one. If the child job(s) now have no pending parents, they +are set to have a state of Ready. We also check if this is the last +job in the batch to complete. If so, we change the batch state to +completed. Lastly, we execute a separate database query that inserts +the appropriate resources for that attempt into the database. + +When we are looking at overall Batch performance, we look at the +metrics of SJ and MJC rates per second for heavy workloads (ex: 1000s +of no-op true jobs). We historically scheduled at 80 jobs per second. We +endeavor to schedule much faster. + + +Canceller +^^^^^^^^^ + +The canceller consists of three background loops that cancel any +ready, running, or creating jobs in batches that have been cancelled +or the job specifically has been cancelled (ie. a parent failed). Fair +share is computed by taking the number of cancellable jobs in each +category and dividing by the total number of cancellable jobs and +multiplying by 300 jobs to cancel in each iteration with a minimum of +20 jobs per user. + + +Billing Updates +^^^^^^^^^^^^^^^ + +To provide users with real time billing and effectively enforce +billing limits, we have the worker send us the job attempts it has +running as well as the current time approximately every 1 minute. We +then update the rollup_time for each job which is guaranteed to be +greater than or equal to the start time and less than or equal to the +end time. The rollup time is then used in billing calculations to +figure out the duration the job has been running thus far. + + +Quota Exhaustion +^^^^^^^^^^^^^^^^ + +There is a mechanism in GCP by which we monitor our current quotas and +assign jobs that can be run in any region to a different region if +we've exceeded our quota. + + + +Cloud Price Monitoring +^^^^^^^^^^^^^^^^^^^^^^ + +We periodically call the corresponding cloud APIs to get up to date +billing information and update the current rates of each product used +accordingly. + + + +Database +-------- + +The batch database has a series of tables, triggers, and stored +procedures that are used to keep track of the state of billing +projects, batches, jobs, attempts, resources, and instances. We +previously discussed how the database operations SJ, MJS, and MJC +work. + +There are three key principles in how the database is structured. + +1. Any values that are dynamic should be separated from tables that +have static state. For example, to represent that a batch is +cancelled, we have a separate ``batches_cancelled`` table rather +than adding a cancelled field to the ``batches`` table. + +2. Any tables with state that is updated in parallel should be +"tokenized" in order to reduce contention for updating rows. For +example, when keeping track of the number of running jobs per user +per instance collection, we'll need to update this count for every +schedule job operation. If there is only one row representing this +value, we'll end up serializing the schedule operations as each one +waits for the exclusive write lock. To avoid this, we have up to +200 rows per value we want to represent where each row has a unique +"token". This way concurrent transactions can update rows +simultaneously and the probability of serialized writes is +equivalent to the birthday problem in mathematics. Note that there +is a drawback to this approach in that queries to obtain the actual +value are more complicated to write as they include an aggregation +and the number of rows to store this in the database can make +queries slower and data more expensive to store. + +Key tables have triggers on them to support billing, job state counts, +and fast cancellation which will be described in more detail below. + + +Billing +^^^^^^^ + +Billing is implemented by keeping track of the resources each attempt +uses as well as the duration of time each attempt runs for. It is +trivial to write a query to compute the cost per attempt or even per +job. However, the query speed is linear in the number of total +attempts when computing the cost for a batch by scanning over the +entire table which is a non-starter for bigger batches. Therefore, we +keep an ``aggregated_batch_resources`` table where each update to the +attempt duration timestamps or inserting a new attempt resource +updates the corresponding batch in the table. This table is +"tokenized" as described above to prevent serialization of attempt +update events. Likewise, we have similar aggregation tables for +billing projects as well as billing project by date. There are two +triggers, one on each of the ``attempts`` and ``attempt_resources`` +table that perform the usage updates and insert the appropriate rows +to these billing tables every time the attempt rollup time is changed +or a new resource is inserted for an attempt. Having these aggregation +tables means we can query the cost of a billing project, billing +project by date, batch, or job by scanning at most 200 records making +this query fast enough for a UI page. The workers send the driver +periodic updates every minute with the elapsed time jobs have been +running for such that we can have "real-time billing". + + +Job State Tracking +^^^^^^^^^^^^^^^^^^ + +To quickly be able to count the number of ready jobs, ready cores, +running jobs, running cores, creating jobs, and creating cores for +computing fair share, we maintain a very small "tokenized" table that +is parameterized by user and instance collection. The values in this +table are automatically updated as a job's state is changed through +the job state diagram. The updates to the ``user_inst_coll_resources`` +table happen in a trigger on the ``jobs`` table. + + +Cancellation +^^^^^^^^^^^^ + +A user can trigger a cancellation of a batch via the cancel button in +the UI or a REST request. The batch system also monitors how much has +been spent in a billing project. Once that limit has been exceeded, +all running batches in the billing project are cancelled. + +Cancellation is the most complicated part of the Batch system. The +goal is to make cancellation as fast as possible such that we don't +waste resources spinning up worker VMs and running user jobs that are +ultimately going to get cancelled. Therefore, we need a way of quickly +notifying the autoscaler and scheduler to not spin up resources or +schedule jobs for batches that have been cancelled. We set a "flag" in +the database indicating the batch has been cancelled via the +``batches_cancelled`` table. This allows the query the scheduler +executes to find Ready jobs to run to not read rows for jobs in batches that +have been cancelled thereby avoiding scheduling them in the first +place. We also execute a similar query for the autoscaler. The only +place where we need to quickly know how many cores we have that are +ready and have not been cancelled is in the fair share calculation via +the ``user_inst_coll_resources`` table. To accomplish a fast update of +this table, we currently keep track of the number of **cancellable** +resources per batch in a tokenized table +``batch_inst_coll_cancellable_resources`` such as the number of +cancellable ready cores. When we execute a cancellation operation, we +quickly count the number of cancellable ready cores or other similar +values from the ``batch_inst_coll_cancellable_resources`` table and +subtract those numbers from the ``user_inst_coll_resources`` table to +have an O(1) update such that the fair share computation can quickly +adjust to the change in demand for resources. + +The background canceller loops iterate through the cancelled jobs as +described above and are marked as Cancelled in the database and +handled accordingly one by one. + +Once a batch has been cancelled, no subsequent updates are allowed to +the batch. + + +Batch Workers +------------- + +Workers are Python web servers running on virtual machines. The Python +web server activates itself with the Batch driver and then accepts +requests to execute jobs. Jobs can take the form of either Docker Jobs +or JVM Jobs. The Docker Jobs are regular jobs that use a user-defined +image and the user-defined source code. JVM jobs are specially +designed for the Query on Batch (QoB) use case. The worker downloads +an approved JAR file to execute a user's query that is stored in cloud +storage. All containers the worker creates are by using `crun` and not +Docker. When the worker has not received any work to do and no jobs +are currently running, it will deactivate itself and shut itself down. + + + +Known Issues +------------ + +- The current database structure serializes MJC operations because the + table ``batches_n_jobs_in_complete_states`` has one row per batch + and each MJC operation tries to update the same row in this + table. +- ``commit_update`` is slow for large updates because we have to + compute the job states by scanning the states of all of a job's + parents. +- If a large batch has multiple distinct regions specified that are not + interweaved, the autoscaler and scheduler can deadlock. From 4120b6e2a493404eef2c29f1b6e43f69b2fca9b4 Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 22 Aug 2023 01:38:47 -0400 Subject: [PATCH 126/180] [ci] fix borked CI (#13473) --- ci/ci/build.py | 12 ++++++++++-- ci/ci/github.py | 34 ++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/ci/ci/build.py b/ci/ci/build.py index d0a67ad5f15..d2e0d1c3b6d 100644 --- a/ci/ci/build.py +++ b/ci/ci/build.py @@ -3,7 +3,7 @@ import logging from collections import Counter, defaultdict from shlex import quote as shq -from typing import Dict, List, Optional, TypedDict +from typing import Dict, List, Optional, Sequence, TypedDict import jinja2 import yaml @@ -96,7 +96,15 @@ class BuildConfigurationError(Exception): class BuildConfiguration: - def __init__(self, code, config_str, scope, *, requested_step_names=(), excluded_step_names=()): + def __init__( + self, + code: Code, + config_str: str, + scope: str, + *, + requested_step_names: Sequence[str] = (), + excluded_step_names: Sequence[str] = (), + ): if len(excluded_step_names) > 0 and scope != 'dev': raise BuildConfigurationError('Excluding build steps is only permitted in a dev scope') diff --git a/ci/ci/github.py b/ci/ci/github.py index 65a171e6baa..5e47139a0c6 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -8,7 +8,7 @@ import secrets from enum import Enum from shlex import quote as shq -from typing import Any, Dict, List, Optional, Set, Union +from typing import Any, Dict, List, Optional, Sequence, Set, Union import aiohttp import gidgethub @@ -16,7 +16,7 @@ import zulip from gear import Database, UserData -from hailtop.batch_client.aioclient import Batch +from hailtop.batch_client.aioclient import Batch, BatchClient from hailtop.config import get_deploy_config from hailtop.utils import RETRY_FUNCTION_SCRIPT, check_shell, check_shell_output @@ -489,7 +489,7 @@ async def _update_github_review_state(self, gh): self.set_review_state(review_state) self.target_branch.state_changed = True - async def _start_build(self, db: Database, batch_client): + async def _start_build(self, db: Database, batch_client: BatchClient): assert await self.authorized(db) # clear current batch @@ -870,7 +870,7 @@ async def _heal_deploy(self, app, batch_client): async with repos_lock: await self._start_deploy(app['db'], batch_client) - async def _update_batch(self, batch_client, db: Database): + async def _update_batch(self, batch_client: BatchClient, db: Database): log.info(f'update batch {self.short_str()}') if self.deployable: @@ -919,7 +919,7 @@ async def _heal(self, app, batch_client, gh): log.info(f'cancel batch {batch.id} for {attrs["pr"]} {attrs["source_sha"]} => {attrs["target_sha"]}') await batch.cancel() - async def _start_deploy(self, db: Database, batch_client): + async def _start_deploy(self, db: Database, batch_client: BatchClient): # not deploying assert not self.deploy_batch or self.deploy_state @@ -970,7 +970,7 @@ async def _start_deploy(self, db: Database, batch_client): ''' await send_zulip_deploy_failure_message(deploy_failure_message, db, self.sha) raise - deploy_batch = await deploy_batch.submit() + await deploy_batch.submit() self.deploy_batch = deploy_batch except concurrent.futures.CancelledError: raise @@ -985,7 +985,7 @@ async def _start_deploy(self, db: Database, batch_client): log.info(f'deleting partially deployed batch {deploy_batch.id}') await deploy_batch.delete() - def checkout_script(self): + def checkout_script(self) -> str: assert self.sha return f''' {clone_or_fetch_script(self.branch.repo.url)} @@ -1005,21 +1005,21 @@ def __init__( extra_config: Optional[Dict[str, Any]] = None, ): self.branch = branch - self.user = userdata['username'] - self.namespace = userdata['namespace_name'] + self.user: str = userdata['username'] + self.namespace: str = userdata['namespace_name'] self.developers = developers self.sha = sha self.extra_config = extra_config - self.deploy_batch = None + self.deploy_batch: Optional[Batch] = None - def short_str(self): + def short_str(self) -> str: return f'br-{self.branch.repo.owner}-{self.branch.repo.name}-{self.branch.name}' - def repo_dir(self): + def repo_dir(self) -> str: return f'repos/{self.branch.repo.short_str()}' - def config(self): + def config(self) -> Dict[str, str]: config = { 'checkout_script': self.checkout_script(), 'branch': self.branch.name, @@ -1033,7 +1033,9 @@ def config(self): config.update(self.extra_config) return config - async def deploy(self, db: Database, batch_client, steps, excluded_steps=()): + async def deploy( + self, db: Database, batch_client: BatchClient, steps: Sequence[str], excluded_steps: Sequence[str] = () + ): assert not self.deploy_batch deploy_batch = None @@ -1070,7 +1072,7 @@ async def deploy(self, db: Database, batch_client, steps, excluded_steps=()): } ) config.build(deploy_batch, self, scope='dev') - deploy_batch = await deploy_batch.submit() + await deploy_batch.submit() self.deploy_batch = deploy_batch return deploy_batch.id finally: @@ -1078,7 +1080,7 @@ async def deploy(self, db: Database, batch_client, steps, excluded_steps=()): log.info(f'deleting partially created deploy batch {deploy_batch.id}') await deploy_batch.delete() - def checkout_script(self): + def checkout_script(self) -> str: return f''' {clone_or_fetch_script(self.branch.repo.url)} From 900a5b5b896affcfaf02d3d8ba101f1b7ba49b51 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 22 Aug 2023 11:16:28 -0400 Subject: [PATCH 127/180] [batch] Move config.json into the container bundle (#13438) ### Background In the world of low-level container runtimes there exists the term "bundle", which basically means the pair of a root filesystem and a `config.json` file containing all of the other necessary information to run the container. If you invoke `crun` or `runc` with `--bundle /path/to/bundle`, the runtime assumes the following: - The configuration file for the container is located at `/path/to/bundle/config.json` - That `config.json` contains a field [`root.path`](https://github.com/opencontainers/runtime-spec/blob/main/config.md#root) that specifies the location of the root filesystem, most commonly as a path relative to `/path/to/bundle`. `crun` offers a way to explicitly reference the location of `config.json` through its `--config` flag. This seems fairly innocuous, but specifying a custom `--config` path can have some unfortunate unintended consequences because it invalidates the assumption in the specification that the configuration resides at `/path/to/bundle/config.json`. Specifically, it breaks [Hooks](https://github.com/opencontainers/runtime-spec/blob/main/config.md#posix-platform-hooks). When a hook is run, the runtime (crun) feeds it the [container state](https://github.com/opencontainers/runtime-spec/blob/main/runtime.md#state), a JSON of information about the container including the `bundle` path. Any hook that attempts to load the `config.json`, like for example, the `nvidia-container-runtime-hook`, will crash. ### Change This change stops using the `--config` flag for crun and instead does the following to create a well-formed bundle: - Instead of the bundle being the merged directory of the container overlay, it is the container's scratch directory - `root.path` is adjusted inside of `config.json` to now point to the merged directory of the container overlay. I've opted to use an absolute path here because why use a relative path. - Move `config.json` into the container scratch directory so that it is inside the root of the bundle directory. --- batch/batch/worker/worker.py | 10 +++------- dev-docs/batch-container-design.md | 6 ++---- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index 87c6d660999..43b6bf943ce 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -812,7 +812,6 @@ def __init__( self.container_scratch = scratch_dir self.container_overlay_path = f'{self.container_scratch}/rootfs_overlay' - self.config_path = f'{self.container_scratch}/config' self.log_path = log_path or f'{self.container_scratch}/container.log' self.resource_usage_path = f'{self.container_scratch}/resource_usage' @@ -1065,9 +1064,7 @@ async def _run_container(self) -> bool: 'crun', 'run', '--bundle', - f'{self.container_overlay_path}/merged', - '--config', - f'{self.config_path}/config.json', + self.container_scratch, self.name, stdin=stdin, stdout=container_log, @@ -1101,8 +1098,7 @@ async def _write_container_config(self): config = await self.container_config() self._validate_container_config(config) - os.makedirs(self.config_path) - with open(f'{self.config_path}/config.json', 'w', encoding='utf-8') as f: + with open(f'{self.container_scratch}/config.json', 'w', encoding='utf-8') as f: f.write(json.dumps(config)) # https://github.com/opencontainers/runtime-spec/blob/master/config.md @@ -1132,7 +1128,7 @@ async def container_config(self): config: Dict[str, Any] = { 'ociVersion': '1.0.1', 'root': { - 'path': '.', + 'path': f'{self.container_overlay_path}/merged', 'readonly': False, }, 'hostname': self.netns.hostname, diff --git a/dev-docs/batch-container-design.md b/dev-docs/batch-container-design.md index ee320db8c43..420cf88a29b 100644 --- a/dev-docs/batch-container-design.md +++ b/dev-docs/batch-container-design.md @@ -40,8 +40,7 @@ scratch/ │ │ │ ├─ io/ (bind mount) │ │ ├─ workdir/ │ ├─ volumes/ -│ ├─ config/ -│ │ ├─ config.json +│ ├─ config.json ├─ main/ │ ├─ rootfs_overlay/ │ │ ├─ upperdir/ (writeable layer) @@ -54,8 +53,7 @@ scratch/ │ │ ├─ workdir/ │ ├─ volumes/ │ │ ├─ image/specified/volume/ -│ ├─ config/ -│ │ ├─ config.json +│ ├─ config.json ├─ output/ │ ├─ ... ``` From d7f5d4c9682b5aa5591cdec41de839421816df80 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 22 Aug 2023 12:31:20 -0400 Subject: [PATCH 128/180] [batch] Add aiomonitor to worker process (#13439) This allows a developer with access inside of the batch worker container to examine currently running `asyncio` tasks inside the worker, get stack traces, examine locals, etc. E.g. ``` monitor >>> ps 367 tasks running +---------------------------------------------------------------------------------------------------------------------------------+ | Task ID State Name Coroutine Created Location Since | +---------------------------------------------------------------------------------------------------------------------------------+ | 140063857549376 PENDING Task-755614 Worker.post_job_started() - - | | 140063857549584 PENDING Task-755568 Worker.run_job() - - | | 140063857549792 PENDING Task-755590 Worker.run_job() - - | | 140063857550000 PENDING Task-755592 Worker.run_job() - - | | 140063857550208 PENDING Task-755372 RequestHandler._handle_request() - - | | 140063857550416 PENDING Task-755637 Worker.run_job() - - | | 140063857550624 PENDING Task-755580 BaseSubprocessTransport._connect_pipes() - - | | 140063857550832 PENDING Task-752239 Worker.run_job() - - | | 140063857551040 PENDING Task-755612 Worker.post_job_started() - - | | 140063857551248 PENDING Task-755610 Worker.post_job_started() - - | | 140063857551456 PENDING Task-755589 Worker.run_job() - - | | 140063857551664 PENDING Task-755613 BaseSubprocessTransport._connect_pipes() - - | | 140063857552288 PENDING Task-755591 Worker.run_job() - - | ``` Wondering do we want this for production or just to activate in test namespaces? --- batch/batch/worker/worker.py | 44 +++++++++++---------- batch/pinned-requirements.txt | 7 ++-- ci/pinned-requirements.txt | 2 + gear/pinned-requirements.txt | 41 +++++++++++++++++-- gear/requirements.txt | 1 + hail/python/dev/pinned-requirements.txt | 34 ++++++++-------- hail/python/hailtop/pinned-requirements.txt | 19 +++++---- hail/python/pinned-requirements.txt | 27 ++++++------- web_common/pinned-requirements.txt | 2 +- 9 files changed, 107 insertions(+), 70 deletions(-) diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index 43b6bf943ce..69636d8b939 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -36,6 +36,7 @@ import aiodocker.images import aiohttp import aiohttp.client_exceptions +import aiomonitor import aiorwlock import async_timeout import orjson @@ -3387,35 +3388,36 @@ async def async_main(): await network_allocator.reserve() worker = Worker(httpx.client_session()) - try: - await worker.run() - finally: + with aiomonitor.start_monitor(asyncio.get_event_loop(), locals=locals()): try: - await worker.shutdown() - log.info('worker shutdown', exc_info=True) + await worker.run() finally: try: - await CLOUD_WORKER_API.close() + await worker.shutdown() + log.info('worker shutdown', exc_info=True) finally: try: - await network_allocator_task_manager.shutdown_and_wait() + await CLOUD_WORKER_API.close() finally: try: - await docker.close() - log.info('docker closed') + await network_allocator_task_manager.shutdown_and_wait() finally: - asyncio.get_event_loop().set_debug(True) - other_tasks = [t for t in asyncio.all_tasks() if t != asyncio.current_task()] - if other_tasks: - log.warning('Tasks immediately after docker close') - dump_all_stacktraces() - _, pending = await asyncio.wait( - other_tasks, timeout=10 * 60, return_when=asyncio.ALL_COMPLETED - ) - for t in pending: - log.warning('Dangling task:') - t.print_stack() - t.cancel() + try: + await docker.close() + log.info('docker closed') + finally: + asyncio.get_event_loop().set_debug(True) + other_tasks = [t for t in asyncio.all_tasks() if t != asyncio.current_task()] + if other_tasks: + log.warning('Tasks immediately after docker close') + dump_all_stacktraces() + _, pending = await asyncio.wait( + other_tasks, timeout=10 * 60, return_when=asyncio.ALL_COMPLETED + ) + for t in pending: + log.warning('Dangling task:') + t.print_stack() + t.cancel() loop = asyncio.get_event_loop() diff --git a/batch/pinned-requirements.txt b/batch/pinned-requirements.txt index b9e0081303b..c0570830847 100644 --- a/batch/pinned-requirements.txt +++ b/batch/pinned-requirements.txt @@ -20,7 +20,7 @@ aiosignal==1.3.1 # -c hail/batch/../hail/python/pinned-requirements.txt # -c hail/batch/../web_common/pinned-requirements.txt # aiohttp -async-timeout==4.0.2 +async-timeout==4.0.3 # via # -c hail/batch/../gear/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt @@ -78,7 +78,7 @@ pandas==2.0.3 # via # -c hail/batch/../hail/python/pinned-requirements.txt # -r hail/batch/requirements.txt -plotly==5.15.0 +plotly==5.16.0 # via # -c hail/batch/../hail/python/pinned-requirements.txt # -r hail/batch/requirements.txt @@ -99,12 +99,13 @@ six==1.16.0 # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt # python-dateutil -tenacity==8.2.2 +tenacity==8.2.3 # via # -c hail/batch/../hail/python/pinned-requirements.txt # plotly typing-extensions==4.7.1 # via + # -c hail/batch/../gear/pinned-requirements.txt # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt # aiodocker diff --git a/ci/pinned-requirements.txt b/ci/pinned-requirements.txt index 34b7938ece0..cc00bdd1b73 100644 --- a/ci/pinned-requirements.txt +++ b/ci/pinned-requirements.txt @@ -24,6 +24,7 @@ charset-normalizer==3.2.0 # requests click==8.1.6 # via + # -c hail/ci/../gear/pinned-requirements.txt # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt # zulip @@ -62,6 +63,7 @@ requests[security]==2.31.0 # zulip typing-extensions==4.7.1 # via + # -c hail/ci/../gear/pinned-requirements.txt # -c hail/ci/../hail/python/dev/pinned-requirements.txt # -c hail/ci/../hail/python/pinned-requirements.txt # zulip diff --git a/gear/pinned-requirements.txt b/gear/pinned-requirements.txt index 58589a13ad7..81bfb533edb 100644 --- a/gear/pinned-requirements.txt +++ b/gear/pinned-requirements.txt @@ -4,6 +4,8 @@ # # pip-compile --output-file=hail/gear/pinned-requirements.txt hail/gear/requirements.txt # +aioconsole==0.6.2 + # via aiomonitor aiohttp==3.8.5 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt @@ -12,6 +14,8 @@ aiohttp==3.8.5 # kubernetes-asyncio aiohttp-session==2.12.0 # via -r hail/gear/requirements.txt +aiomonitor==0.5.0 + # via -r hail/gear/requirements.txt aiomysql==0.2.0 # via -r hail/gear/requirements.txt aiosignal==1.3.1 @@ -19,7 +23,7 @@ aiosignal==1.3.1 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp -async-timeout==4.0.2 +async-timeout==4.0.3 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt @@ -30,6 +34,7 @@ attrs==23.1.0 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp + # aiomonitor cachetools==5.3.1 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt @@ -49,6 +54,12 @@ charset-normalizer==3.2.0 # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # requests +click==8.1.6 + # via + # -c hail/gear/../hail/python/dev/pinned-requirements.txt + # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt + # -c hail/gear/../hail/python/pinned-requirements.txt + # aiomonitor frozenlist==1.4.0 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt @@ -60,7 +71,7 @@ google-api-core==2.11.1 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # google-api-python-client -google-api-python-client==2.95.0 +google-api-python-client==2.96.0 # via google-cloud-profiler google-auth==2.22.0 # via @@ -76,7 +87,7 @@ google-auth-httplib2==0.1.0 # google-cloud-profiler google-cloud-profiler==3.1.0 # via -r hail/gear/requirements.txt -googleapis-common-protos==1.59.1 +googleapis-common-protos==1.60.0 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt @@ -92,6 +103,11 @@ idna==3.4 # -c hail/gear/../hail/python/pinned-requirements.txt # requests # yarl +janus==1.0.0 + # via + # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt + # -c hail/gear/../hail/python/pinned-requirements.txt + # aiomonitor kubernetes-asyncio==19.15.1 # via -r hail/gear/requirements.txt multidict==6.0.4 @@ -100,7 +116,7 @@ multidict==6.0.4 # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # yarl -orjson==3.9.2 +orjson==3.9.4 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt @@ -112,6 +128,10 @@ prometheus-client==0.17.1 # -c hail/gear/../hail/python/dev/pinned-requirements.txt # -r hail/gear/requirements.txt # prometheus-async +prompt-toolkit==3.0.39 + # via + # -c hail/gear/../hail/python/dev/pinned-requirements.txt + # aiomonitor protobuf==3.20.2 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt @@ -175,6 +195,15 @@ sortedcontainers==2.4.0 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # -r hail/gear/requirements.txt +terminaltables==3.1.10 + # via aiomonitor +typing-extensions==4.7.1 + # via + # -c hail/gear/../hail/python/dev/pinned-requirements.txt + # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt + # -c hail/gear/../hail/python/pinned-requirements.txt + # aiomonitor + # janus uritemplate==4.1.1 # via google-api-python-client urllib3==1.26.16 @@ -185,6 +214,10 @@ urllib3==1.26.16 # google-auth # kubernetes-asyncio # requests +wcwidth==0.2.6 + # via + # -c hail/gear/../hail/python/dev/pinned-requirements.txt + # prompt-toolkit wrapt==1.15.0 # via # -c hail/gear/../hail/python/dev/pinned-requirements.txt diff --git a/gear/requirements.txt b/gear/requirements.txt index a75dd5cb217..91f2f5d581b 100644 --- a/gear/requirements.txt +++ b/gear/requirements.txt @@ -7,6 +7,7 @@ -c ../hail/python/dev/pinned-requirements.txt aiohttp_session>=2.7,<2.13 +aiomonitor>=0.4.5,<1 aiomysql>=0.0.20,<1 google-cloud-profiler<4.0.0 kubernetes-asyncio>=19.15.1,<20 diff --git a/hail/python/dev/pinned-requirements.txt b/hail/python/dev/pinned-requirements.txt index 4e8d891420e..bbac9d36684 100644 --- a/hail/python/dev/pinned-requirements.txt +++ b/hail/python/dev/pinned-requirements.txt @@ -56,7 +56,7 @@ click==8.1.6 # -r hail/hail/python/dev/requirements.txt # black # curlylint -comm==0.1.3 +comm==0.1.4 # via # ipykernel # ipywidgets @@ -68,7 +68,7 @@ curlylint==0.13.1 # via -r hail/hail/python/dev/requirements.txt cycler==0.11.0 # via matplotlib -debugpy==1.6.7 +debugpy==1.6.7.post1 # via ipykernel decorator==4.4.2 # via @@ -85,7 +85,7 @@ docutils==0.18.1 # nbsphinx # sphinx # sphinx-rtd-theme -exceptiongroup==1.1.2 +exceptiongroup==1.1.3 # via # anyio # pytest @@ -95,7 +95,7 @@ executing==1.2.0 # via stack-data fastjsonschema==2.18.0 # via nbformat -fonttools==4.41.1 +fonttools==4.42.0 # via matplotlib fqdn==1.5.1 # via jsonschema @@ -117,7 +117,7 @@ importlib-metadata==6.8.0 # jupyterlab-server # nbconvert # sphinx -importlib-resources==6.0.0 +importlib-resources==6.0.1 # via # jsonschema # jsonschema-specifications @@ -126,7 +126,7 @@ importlib-resources==6.0.0 # notebook iniconfig==2.0.0 # via pytest -ipykernel==6.25.0 +ipykernel==6.25.1 # via # jupyter # jupyter-console @@ -160,7 +160,7 @@ json5==0.9.14 # via jupyterlab-server jsonpointer==2.4 # via jsonschema -jsonschema[format-nongpl]==4.18.4 +jsonschema[format-nongpl]==4.19.0 # via # jupyter-events # jupyterlab-server @@ -193,7 +193,7 @@ jupyter-events==0.7.0 # via jupyter-server jupyter-lsp==2.2.0 # via jupyterlab -jupyter-server==2.7.0 +jupyter-server==2.7.1 # via # jupyter-lsp # jupyterlab @@ -202,7 +202,7 @@ jupyter-server==2.7.0 # notebook-shim jupyter-server-terminals==0.4.4 # via jupyter-server -jupyterlab==4.0.3 +jupyterlab==4.0.5 # via notebook jupyterlab-pygments==0.2.2 # via nbconvert @@ -252,11 +252,11 @@ nbformat==5.9.2 # nbsphinx nbsphinx==0.9.2 # via -r hail/hail/python/dev/requirements.txt -nest-asyncio==1.5.6 +nest-asyncio==1.5.7 # via # -c hail/hail/python/dev/../pinned-requirements.txt # ipykernel -notebook==7.0.1 +notebook==7.0.2 # via jupyter notebook-shim==0.2.3 # via @@ -267,7 +267,7 @@ numpy==1.24.4 # -c hail/hail/python/dev/../pinned-requirements.txt # contourpy # matplotlib -overrides==7.3.1 +overrides==7.4.0 # via jupyter-server packaging==23.1 # via @@ -329,7 +329,7 @@ pycparser==2.21 # via # -c hail/hail/python/dev/../pinned-requirements.txt # cffi -pygments==2.15.1 +pygments==2.16.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt # ipython @@ -384,7 +384,7 @@ pyyaml==6.0.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt # jupyter-events -pyzmq==25.1.0 +pyzmq==25.1.1 # via # ipykernel # jupyter-client @@ -395,7 +395,7 @@ qtconsole==5.4.3 # via jupyter qtpy==2.3.1 # via qtconsole -referencing==0.30.0 +referencing==0.30.2 # via # jsonschema # jsonschema-specifications @@ -417,7 +417,7 @@ rpds-py==0.9.2 # via # jsonschema # referencing -ruff==0.0.282 +ruff==0.0.284 # via -r hail/hail/python/dev/requirements.txt send2trash==1.8.2 # via jupyter-server @@ -481,7 +481,7 @@ tomli==2.0.1 # pytest tomlkit==0.12.1 # via pylint -tornado==6.3.2 +tornado==6.3.3 # via # -c hail/hail/python/dev/../pinned-requirements.txt # ipykernel diff --git a/hail/python/hailtop/pinned-requirements.txt b/hail/python/hailtop/pinned-requirements.txt index d0b261fe105..85c381c8ffd 100644 --- a/hail/python/hailtop/pinned-requirements.txt +++ b/hail/python/hailtop/pinned-requirements.txt @@ -10,19 +10,19 @@ aiohttp==3.8.5 # via -r hail/hail/python/hailtop/requirements.txt aiosignal==1.3.1 # via aiohttp -async-timeout==4.0.2 +async-timeout==4.0.3 # via aiohttp attrs==23.1.0 # via aiohttp azure-common==1.1.28 # via azure-mgmt-storage -azure-core==1.28.0 +azure-core==1.29.2 # via # azure-identity # azure-mgmt-core # azure-storage-blob # msrest -azure-identity==1.13.0 +azure-identity==1.14.0 # via -r hail/hail/python/hailtop/requirements.txt azure-mgmt-core==1.4.0 # via azure-mgmt-storage @@ -30,9 +30,9 @@ azure-mgmt-storage==20.1.0 # via -r hail/hail/python/hailtop/requirements.txt azure-storage-blob==12.17.0 # via -r hail/hail/python/hailtop/requirements.txt -boto3==1.28.11 +boto3==1.28.26 # via -r hail/hail/python/hailtop/requirements.txt -botocore==1.31.11 +botocore==1.31.26 # via # -r hail/hail/python/hailtop/requirements.txt # boto3 @@ -86,7 +86,7 @@ google-crc32c==1.5.0 # via google-resumable-media google-resumable-media==2.5.0 # via google-cloud-storage -googleapis-common-protos==1.59.1 +googleapis-common-protos==1.60.0 # via google-api-core humanize==1.1.0 # via -r hail/hail/python/hailtop/requirements.txt @@ -118,11 +118,11 @@ multidict==6.0.4 # via # aiohttp # yarl -nest-asyncio==1.5.6 +nest-asyncio==1.5.7 # via -r hail/hail/python/hailtop/requirements.txt oauthlib==3.2.2 # via requests-oauthlib -orjson==3.9.2 +orjson==3.9.4 # via -r hail/hail/python/hailtop/requirements.txt portalocker==2.7.0 # via msal-extensions @@ -141,7 +141,7 @@ pycares==4.3.0 # via aiodns pycparser==2.21 # via cffi -pygments==2.15.1 +pygments==2.16.1 # via rich pyjwt[crypto]==2.8.0 # via msal @@ -170,7 +170,6 @@ s3transfer==0.6.1 six==1.16.0 # via # azure-core - # azure-identity # google-auth # isodate # jproperties diff --git a/hail/python/pinned-requirements.txt b/hail/python/pinned-requirements.txt index e432e69eb5c..a37e5e1985c 100644 --- a/hail/python/pinned-requirements.txt +++ b/hail/python/pinned-requirements.txt @@ -16,7 +16,7 @@ aiosignal==1.3.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # aiohttp -async-timeout==4.0.2 +async-timeout==4.0.3 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # aiohttp @@ -32,14 +32,14 @@ azure-common==1.1.28 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-mgmt-storage -azure-core==1.28.0 +azure-core==1.29.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-identity # azure-mgmt-core # azure-storage-blob # msrest -azure-identity==1.13.0 +azure-identity==1.14.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -57,11 +57,11 @@ azure-storage-blob==12.17.0 # -r hail/hail/python/hailtop/requirements.txt bokeh==3.1.1 # via -r hail/hail/python/requirements.txt -boto3==1.28.11 +boto3==1.28.26 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -botocore==1.31.11 +botocore==1.31.26 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -147,7 +147,7 @@ google-resumable-media==2.5.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # google-cloud-storage -googleapis-common-protos==1.59.1 +googleapis-common-protos==1.60.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # google-api-core @@ -200,7 +200,7 @@ multidict==6.0.4 # -c hail/hail/python/hailtop/pinned-requirements.txt # aiohttp # yarl -nest-asyncio==1.5.6 +nest-asyncio==1.5.7 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -215,7 +215,7 @@ oauthlib==3.2.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # requests-oauthlib -orjson==3.9.2 +orjson==3.9.4 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -231,7 +231,7 @@ parsimonious==0.10.0 # via -r hail/hail/python/requirements.txt pillow==10.0.0 # via bokeh -plotly==5.15.0 +plotly==5.16.0 # via -r hail/hail/python/requirements.txt portalocker==2.7.0 # via @@ -263,7 +263,7 @@ pycparser==2.21 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # cffi -pygments==2.15.1 +pygments==2.16.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # rich @@ -289,7 +289,7 @@ pyyaml==6.0.1 # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt # bokeh -regex==2023.6.3 +regex==2023.8.8 # via parsimonious requests==2.31.0 # via @@ -323,7 +323,6 @@ six==1.16.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-core - # azure-identity # google-auth # isodate # jproperties @@ -336,9 +335,9 @@ tabulate==0.9.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -tenacity==8.2.2 +tenacity==8.2.3 # via plotly -tornado==6.3.2 +tornado==6.3.3 # via bokeh typer==0.9.0 # via diff --git a/web_common/pinned-requirements.txt b/web_common/pinned-requirements.txt index 6440ef1975a..a38db95428e 100644 --- a/web_common/pinned-requirements.txt +++ b/web_common/pinned-requirements.txt @@ -16,7 +16,7 @@ aiosignal==1.3.1 # -c hail/web_common/../gear/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt # aiohttp -async-timeout==4.0.2 +async-timeout==4.0.3 # via # -c hail/web_common/../gear/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt From 70359acb3609963f7233b940a4e040e35da0c659 Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 22 Aug 2023 13:55:39 -0400 Subject: [PATCH 129/180] [query] fix services-jvm-test and fs-jvm-test Make targets (#13471) These have not worked in a long time. --- hail/Makefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hail/Makefile b/hail/Makefile index dabe146d3a1..f4d1764016a 100644 --- a/hail/Makefile +++ b/hail/Makefile @@ -119,14 +119,20 @@ ifdef HAIL_COMPILE_NATIVES services-jvm-test: native-lib-prebuilt endif services-jvm-test: $(SCALA_BUILD_INFO) $(JAR_SOURCES) $(JAR_TEST_SOURCES) - +./pgradle testServices $(GRADLE_ARGS) $(GRADLE_TEST_ARGS) + ./gradlew testServices $(GRADLE_ARGS) $(GRADLE_TEST_ARGS) .PHONY: services-jvm-test ifdef HAIL_COMPILE_NATIVES fs-jvm-test: native-lib-prebuilt endif fs-jvm-test: $(SCALA_BUILD_INFO) $(JAR_SOURCES) $(JAR_TEST_SOURCES) - +./pgradle testFS $(GRADLE_ARGS) $(GRADLE_TEST_ARGS) + [ -n $(HAIL_CLOUD) ] # call like make fs-jvm-test HAIL_CLOUD=gcp or azure + [ -n $(NAMESPACE) ] # call like make fs-jvm-test NAMEPSPACE=default + HAIL_CLOUD=$(HAIL_CLOUD) \ + HAIL_DEFAULT_NAMESPACE=$(NAMESPACE) \ + HAIL_FS_TEST_CLOUD_RESOURCES_URI=$(CLOUD_HAIL_TEST_RESOURCES_DIR)fs \ + HAIL_TEST_STORAGE_URI=$(TEST_STORAGE_URI) \ + ./gradlew testFS $(GRADLE_ARGS) $(GRADLE_TEST_ARGS) # javac args from compileJava in build.gradle $(BUILD_DEBUG_PREFIX)/%.class: src/debug/scala/%.java From 86f97735d17cd683a7067729420904a856042a6c Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 22 Aug 2023 15:12:42 -0400 Subject: [PATCH 130/180] [batch] Turn on compaction in test and dev (#13476) We weren't actually testing the compaction in test and dev, which is probably why we had those initial errors in production. --- batch/sql/turn_on_billing_compaction.py | 20 ++++++++++++++++++++ build.yaml | 3 +++ 2 files changed, 23 insertions(+) create mode 100644 batch/sql/turn_on_billing_compaction.py diff --git a/batch/sql/turn_on_billing_compaction.py b/batch/sql/turn_on_billing_compaction.py new file mode 100644 index 00000000000..c6a812eb07f --- /dev/null +++ b/batch/sql/turn_on_billing_compaction.py @@ -0,0 +1,20 @@ +import os +import asyncio +from gear import Database + + +async def main(): + if os.environ['HAIL_SCOPE'] == 'deploy': + return + + db = Database() + await db.async_init() + await db.execute_update( + ''' +UPDATE feature_flags +SET compact_billing_tables = 1; +''') + await db.async_close() + +loop = asyncio.get_event_loop() +loop.run_until_complete(main()) diff --git a/build.yaml b/build.yaml index 7a4e4b67e31..1274f633630 100644 --- a/build.yaml +++ b/build.yaml @@ -2204,6 +2204,9 @@ steps: - name: jobs-after-update-simple.sql script: /io/sql/jobs-after-update-simple.sql online: true + - name: turn-on-billing-compaction + script: /io/sql/turn_on_billing_compaction.py + online: true inputs: - from: /repo/batch/sql to: /io/sql From 3a8be2b37ec387cbf0664354148a66e5930f2f88 Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 22 Aug 2023 16:27:14 -0400 Subject: [PATCH 131/180] [hailtop.batch_client] Merge Unsubmitted/Submitted Job into Job (#13467) Follow up to #13458 for making adding job groups simpler. --- batch/test/test_batch.py | 13 +- batch/test/test_dag.py | 2 +- .../hailtop/batch/batch_pool_executor.py | 4 +- hail/python/hailtop/batch_client/__init__.py | 5 + hail/python/hailtop/batch_client/aioclient.py | 233 +++++++----------- hail/python/hailtop/batch_client/client.py | 19 +- 6 files changed, 108 insertions(+), 168 deletions(-) diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 90bd224ef1e..8e1190c4c1e 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -10,6 +10,7 @@ from hailtop import httpx from hailtop.auth import hail_credentials from hailtop.batch.backend import HAIL_GENETICS_HAILTOP_IMAGE +from hailtop.batch_client import BatchNotCreatedError, JobNotSubmittedError from hailtop.batch_client.client import Batch, BatchClient from hailtop.config import get_deploy_config, get_user_config from hailtop.test_utils import skip_in_azure @@ -252,17 +253,17 @@ def test_unsubmitted_state(client: BatchClient): b = create_batch(client) j = b.create_job(DOCKER_ROOT_IMAGE, ['echo', 'test']) - with pytest.raises(ValueError): + with pytest.raises(BatchNotCreatedError): j.batch_id # pylint: disable=pointless-statement - with pytest.raises(ValueError): + with pytest.raises(JobNotSubmittedError): j.id # pylint: disable=pointless-statement - with pytest.raises(ValueError): + with pytest.raises(JobNotSubmittedError): j.status() - with pytest.raises(ValueError): + with pytest.raises(JobNotSubmittedError): j.is_complete() - with pytest.raises(ValueError): + with pytest.raises(JobNotSubmittedError): j.log() - with pytest.raises(ValueError): + with pytest.raises(JobNotSubmittedError): j.wait() diff --git a/batch/test/test_dag.py b/batch/test/test_dag.py index c463e372d13..08eb96a217e 100644 --- a/batch/test/test_dag.py +++ b/batch/test/test_dag.py @@ -35,7 +35,7 @@ def test_missing_parent_is_400(client): try: batch = create_batch(client) fake_job = aioclient.Job.unsubmitted_job(batch._async_batch, 10000) - fake_job = Job.from_async_job(fake_job) + fake_job = Job(fake_job) batch.create_job(DOCKER_ROOT_IMAGE, command=['echo', 'head'], parents=[fake_job]) batch.submit() except ValueError as err: diff --git a/hail/python/hailtop/batch/batch_pool_executor.py b/hail/python/hailtop/batch/batch_pool_executor.py index 77f0aabf366..ef2f30925c3 100644 --- a/hail/python/hailtop/batch/batch_pool_executor.py +++ b/hail/python/hailtop/batch/batch_pool_executor.py @@ -546,8 +546,8 @@ async def async_result(self, timeout: Optional[Union[float, int]] = None): async def _async_fetch_result(self): try: - await self.job.wait() - main_container_status = self.job._status['status']['container_statuses']['main'] + status = await self.job.wait() + main_container_status = status['status']['container_statuses']['main'] if main_container_status['state'] == 'error': raise ValueError( f"submitted job failed:\n{main_container_status['error']}") diff --git a/hail/python/hailtop/batch_client/__init__.py b/hail/python/hailtop/batch_client/__init__.py index a62bf2a09d7..60de0b330b8 100644 --- a/hail/python/hailtop/batch_client/__init__.py +++ b/hail/python/hailtop/batch_client/__init__.py @@ -1,6 +1,11 @@ from . import client, aioclient, parse +from .aioclient import BatchAlreadyCreatedError, BatchNotCreatedError, JobAlreadySubmittedError, JobNotSubmittedError __all__ = [ + 'BatchAlreadyCreatedError', + 'BatchNotCreatedError', + 'JobAlreadySubmittedError', + 'JobNotSubmittedError', 'client', 'aioclient', 'parse', diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index 8c0966ff795..9fcda0fc8f7 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -22,6 +22,22 @@ log = logging.getLogger('batch_client.aioclient') +class JobAlreadySubmittedError(Exception): + pass + + +class JobNotSubmittedError(Exception): + pass + + +class AbsoluteJobId(int): + pass + + +class InUpdateJobId(int): + pass + + class Job: @staticmethod def _get_error(job_status, task): @@ -157,155 +173,65 @@ def _get_duration(container_status): return sum(durations) @staticmethod - def unsubmitted_job(batch, job_id): - assert isinstance(batch, Batch) - _job = UnsubmittedJob(batch, job_id) - return Job(_job) + def submitted_job(batch: 'Batch', job_id: int, _status: Optional[dict] = None): + return Job(batch, AbsoluteJobId(job_id), _status=_status) @staticmethod - def submitted_job(batch, job_id, _status=None): - assert isinstance(batch, Batch) - _job = SubmittedJob(batch, job_id, _status) - return Job(_job) + def unsubmitted_job(batch: 'Batch', job_id: int): + return Job(batch, InUpdateJobId(job_id)) - def __init__(self, job): - self._job = job - - @property - def batch_id(self): - return self._job.batch_id - - @property - def job_id(self): - return self._job.job_id - - @property - def id(self): - return self._job.id - - async def attributes(self): - return await self._job.attributes() - - async def is_complete(self): - return await self._job.is_complete() - - async def is_running(self): - return await self._job.is_running() + def __init__(self, + batch: 'Batch', + job_id: Union[AbsoluteJobId, InUpdateJobId], + *, + _status: Optional[dict] = None): + self._batch = batch + self._job_id = job_id + self._status = _status - async def is_pending(self): - return await self._job.is_pending() + def _raise_if_not_submitted(self): + if not self.is_submitted: + raise JobNotSubmittedError - async def is_ready(self): - return await self._job.is_ready() + def _raise_if_submitted(self): + if self.is_submitted: + raise JobAlreadySubmittedError - # { - # batch_id: int - # job_id: int - # user: str - # billing_project: str - # name: optional(str) - # state: str (Ready, Running, Success, Error, Failure, Cancelled) - # exit_code: optional(int) - # duration: optional(int) (msecs) - # msec_mcpu: int - # cost: float - # } - async def status(self): - return await self._job.status() + def _submit(self, in_update_start_job_id: int): + self._raise_if_submitted() + self._job_id = AbsoluteJobId(in_update_start_job_id + self._job_id - 1) @property - def _status(self): - return self._job._status - - async def wait(self): - return await self._job.wait() - - async def _wait_for_states(self, *states: str): - return await self._job._wait_for_states(*states) - - async def container_log(self, container_name: str): - return await self._job.container_log(container_name) - - async def log(self): - return await self._job.log() - - async def attempts(self): - return await self._job.attempts() - - -class UnsubmittedJob: - def _submit(self, update_start_job_id: int): - return SubmittedJob(self._batch, self._job_id + update_start_job_id - 1) - - def __init__(self, batch: 'Batch', job_id: int): - self._batch = batch - self._job_id = job_id + def is_submitted(self): + return isinstance(self._job_id, AbsoluteJobId) @property - def batch_id(self): - raise ValueError("cannot get the batch_id of an unsubmitted job") + def batch_id(self) -> int: + return self._batch.id @property - def job_id(self): - raise ValueError("cannot get the job_id of an unsubmitted job") + def job_id(self) -> int: + self._raise_if_not_submitted() + return self._job_id @property - def id(self): - raise ValueError("cannot get the id of an unsubmitted job") - - async def attributes(self): - raise ValueError("cannot get the attributes of an unsubmitted job") - - async def is_complete(self): - raise ValueError("cannot determine if an unsubmitted job is complete") - - async def is_running(self): - raise ValueError("cannot determine if an unsubmitted job is running") - - async def is_pending(self): - raise ValueError("cannot determine if an unsubmitted job is pending") - - async def is_ready(self): - raise ValueError("cannot determine if an unsubmitted job is ready") - - async def status(self): - raise ValueError("cannot get the status of an unsubmitted job") + def id(self) -> Tuple[int, int]: + self._raise_if_not_submitted() + return (self.batch_id, self.job_id) @property - def _status(self): - raise ValueError("cannot get the _status of an unsubmitted job") - - async def wait(self): - raise ValueError("cannot wait on an unsubmitted job") - - async def _wait_for_states(self, *states: str): - raise ValueError("cannot _wait_for_states on an unsubmitted job") - - async def container_log(self, container_name: str): - raise ValueError("cannot get the log of an unsubmitted job") - - async def log(self): - raise ValueError("cannot get the log of an unsubmitted job") - - async def attempts(self): - raise ValueError("cannot get the attempts of an unsubmitted job") - - -class SubmittedJob: - def __init__(self, batch, job_id, _status=None): - self._batch = batch - self.batch_id = batch.id - self.job_id = job_id - self.id = (self.batch_id, self.job_id) - self._status = _status + def _client(self) -> 'BatchClient': + return self._batch._client async def attributes(self): if not self._status: await self.status() + assert self._status is not None return self._status['attributes'] async def _is_job_in_state(self, states): await self.status() + assert self._status is not None state = self._status['state'] return state in states @@ -321,9 +247,23 @@ async def is_pending(self): async def is_ready(self): return await self._is_job_in_state(['Ready']) - async def status(self): - resp = await self._batch._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}') + # { + # batch_id: int + # job_id: int + # user: str + # billing_project: str + # name: optional(str) + # state: str (Ready, Running, Success, Error, Failure, Cancelled) + # exit_code: optional(int) + # duration: optional(int) (msecs) + # msec_mcpu: int + # cost: float + # } + async def status(self) -> dict: + self._raise_if_not_submitted() + resp = await self._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}') self._status = await resp.json() + assert self._status is not None return self._status async def wait(self): @@ -338,15 +278,18 @@ async def _wait_for_states(self, *states: str): await sleep_before_try(tries) async def container_log(self, container_name: str) -> bytes: - async with await self._batch._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/log/{container_name}') as resp: + self._raise_if_not_submitted() + async with await self._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/log/{container_name}') as resp: return await resp.read() async def log(self): - resp = await self._batch._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/log') + self._raise_if_not_submitted() + resp = await self._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/log') return await resp.json() async def attempts(self): - resp = await self._batch._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/attempts') + self._raise_if_not_submitted() + resp = await self._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}/attempts') return await resp.json() @@ -355,7 +298,7 @@ def __init__(self, used_fast_path: Optional[bool] = None): self.used_fast_path = used_fast_path -class BatchNotSubmittedError(Exception): +class BatchNotCreatedError(Exception): pass @@ -392,7 +335,7 @@ def __init__(self, def _raise_if_not_created(self): if not self.is_created: - raise BatchNotSubmittedError + raise BatchNotCreatedError def _raise_if_created(self): if self.is_created: @@ -576,23 +519,21 @@ def _create_job(self, absolute_parent_ids = [] in_update_parent_ids = [] - foreign_batches: List[Union[SubmittedJob, UnsubmittedJob]] = [] + foreign_batches: List[Job] = [] invalid_job_ids = [] for parent in parents: - job = parent._job - if isinstance(job, UnsubmittedJob): - if job._batch != self: - foreign_batches.append(job) - elif not 0 < job._job_id < self._job_idx: - invalid_job_ids.append(job) + if not parent.is_submitted: + assert isinstance(parent._job_id, InUpdateJobId) + if parent._batch != self: + foreign_batches.append(parent) + elif not 0 < parent._job_id < self._job_idx: + invalid_job_ids.append(parent._job_id) else: - in_update_parent_ids.append(job._job_id) + in_update_parent_ids.append(parent._job_id) + elif not self.is_created or parent._batch.id != self.id: + foreign_batches.append(parent) else: - assert isinstance(job, SubmittedJob) - if not self.is_created or job._batch.id != self.id: - foreign_batches.append(job) - else: - absolute_parent_ids.append(job.job_id) + absolute_parent_ids.append(parent._job_id) error_msg = [] if len(foreign_batches) != 0: @@ -880,7 +821,7 @@ async def submit(self, for j in self._jobs: assert start_job_id is not None - j._job = j._job._submit(start_job_id) + j._submit(start_job_id) self._job_specs = [] self._jobs = [] diff --git a/hail/python/hailtop/batch_client/client.py b/hail/python/hailtop/batch_client/client.py index d1fec0132a5..4ddcb051dd7 100644 --- a/hail/python/hailtop/batch_client/client.py +++ b/hail/python/hailtop/batch_client/client.py @@ -31,15 +31,8 @@ def exit_code(job_status): def total_duration_msecs(job_status): return aioclient.Job.total_duration_msecs(job_status) - @classmethod - def from_async_job(cls, job: aioclient.Job): - j = object.__new__(cls) - j._async_job = job - return j - - def __init__(self, batch: aioclient.Batch, job_id: int, _status=None): - j = aioclient.SubmittedJob(batch, job_id, _status) - self._async_job: aioclient.Job = aioclient.Job(j) + def __init__(self, async_job: aioclient.Job): + self._async_job: aioclient.Job = async_job @property def _status(self): @@ -168,7 +161,7 @@ def jobs(self, q=None, version=None): def get_job(self, job_id: int) -> Job: j = async_to_blocking(self._async_batch.get_job(job_id)) - return Job.from_async_job(j) + return Job(j) def get_job_log(self, job_id: int) -> Optional[Dict[str, Any]]: return async_to_blocking(self._async_batch.get_job_log(job_id)) @@ -209,7 +202,7 @@ def create_job(self, network=network, unconfined=unconfined, user_code=user_code, regions=regions) - return Job.from_async_job(async_job) + return Job(async_job) def create_jvm_job(self, command, *, profile: bool = False, parents=None, **kwargs) -> Job: if parents: @@ -217,7 +210,7 @@ def create_jvm_job(self, command, *, profile: bool = False, parents=None, **kwar async_job = self._async_batch.create_jvm_job(command, profile=profile, parents=parents, **kwargs) - return Job.from_async_job(async_job) + return Job(async_job) def submit(self, *args, **kwargs): async_to_blocking(self._async_batch.submit(*args, **kwargs)) @@ -253,7 +246,7 @@ def list_batches(self, q=None, last_batch_id=None, limit=2**64, version=None): def get_job(self, batch_id, job_id): j = async_to_blocking(self._async_client.get_job(batch_id, job_id)) - return Job.from_async_job(j) + return Job(j) def get_job_log(self, batch_id, job_id) -> Optional[Dict[str, Any]]: log = async_to_blocking(self._async_client.get_job_log(batch_id, job_id)) From 1d80c26f0b2a71d45c972190140d5e34e3c039d9 Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 22 Aug 2023 20:21:06 -0400 Subject: [PATCH 132/180] [query] eliminate use of type in ldscsim (#13477) I was running `pyright` on Hail for other reasons and it pointed out we should not use `type` in this way. --- hail/python/hail/experimental/ldscsim.py | 37 ++++++++++++------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/hail/python/hail/experimental/ldscsim.py b/hail/python/hail/experimental/ldscsim.py index 1b3705c9544..defe5820452 100644 --- a/hail/python/hail/experimental/ldscsim.py +++ b/hail/python/hail/experimental/ldscsim.py @@ -95,8 +95,8 @@ def simulate_phenotypes(mt, genotype, h2, pi=None, rg=None, annot=None, popstrat :class:`.MatrixTable` with simulated betas and phenotypes, simulated according to specified model. """ - h2 = h2.tolist() if type(h2) is np.ndarray else ([h2] if type(h2) is not list else h2) - pi = pi.tolist() if type(pi) is np.ndarray else pi + h2 = h2.tolist() if isinstance(h2, np.ndarray) else ([h2] if not isinstance(h2, list) else h2) + pi = pi.tolist() if isinstance(pi, np.ndarray) else pi uid = Env.get_uid(base=100) mt = annotate_all(mt=mt, row_exprs={} if annot is None else {'annot_' + uid: annot}, @@ -178,12 +178,12 @@ def make_betas(mt, h2, pi=None, annot=None, rg=None): covariance matrix for multitrait simulation was not positive semi-definite. """ - h2 = h2.tolist() if type(h2) is np.ndarray else ( - [h2] if type(h2) is not list else h2) - pi = pi.tolist() if type(pi) is np.ndarray else ( - [pi] if type(pi) is not list else pi) - rg = rg.tolist() if type(rg) is np.ndarray else ( - [rg] if type(rg) is not list else rg) + h2 = h2.tolist() if isinstance(h2, np.ndarray) else ( + [h2] if not isinstance(h2, list) else h2) + pi = pi.tolist() if isinstance(pi, np.ndarray) else ( + [pi] if not isinstance(pi, list) else pi) + rg = rg.tolist() if isinstance(rg, np.ndarray) else ( + [rg] if not isinstance(rg, list) else rg) assert (all(x >= 0 and x <= 1 for x in h2) ), 'h2 values must be between 0 and 1' assert (pi is not [None]) or all( @@ -193,7 +193,7 @@ def make_betas(mt, h2, pi=None, annot=None, rg=None): if annot is not None: # multi-trait annotation-informed assert rg == [ None], 'Correlated traits not supported for annotation-informed model' - h2 = h2 if type(h2) is list else [h2] + h2 = h2 if isinstance(h2, list) else [h2] annot_sum = mt.aggregate_rows(hl.agg.sum(annot)) mt = mt.annotate_rows(beta=hl.literal(h2).map( lambda x: hl.rand_norm(0, hl.sqrt(annot * x / (annot_sum * M))))) @@ -260,8 +260,8 @@ def multitrait_inf(mt, h2=None, rg=None, cov_matrix=None, seed=None): covariance matrix was not positive semi-definite. """ uid = Env.get_uid(base=100) - h2 = (h2.tolist() if type(h2) is np.ndarray else ([h2] if type(h2) is not list else h2)) - rg = rg.tolist() if type(rg) is np.ndarray else ([rg] if type(rg) is not list else rg) + h2 = (h2.tolist() if isinstance(h2, np.ndarray) else ([h2] if not isinstance(h2, list) else h2)) + rg = rg.tolist() if isinstance(rg, np.ndarray) else ([rg] if not isinstance(rg, list) else rg) assert (all(x >= 0 and x <= 1 for x in h2)), 'h2 values must be between 0 and 1' assert h2 is not [None] or cov_matrix is not None, 'h2 and cov_matrix cannot both be None' M = mt.count_rows() @@ -473,7 +473,7 @@ def get_cov_matrix(h2, rg, psd_rg=False): ), 'h2 values must be between 0 and 1' assert (all(x >= -1 and x <= 1 for x in rg) ), 'rg values must be between -1 and 1' - rg = np.asarray(rg) if type(rg) is list else rg + rg = np.asarray(rg) if isinstance(rg, list) else rg n_rg = len(rg) n_h2 = len(h2) # expected number of rg values, given number of traits @@ -570,8 +570,8 @@ def calculate_phenotypes(mt, genotype, beta, h2, popstrat=None, popstrat_var=Non :class:`.MatrixTable` with simulated phenotype as column field. """ print('calculating phenotype') - h2 = h2.tolist() if type(h2) is np.ndarray else ( - [h2] if type(h2) is not list else h2) + h2 = h2.tolist() if isinstance(h2, np.ndarray) else ( + [h2] if not isinstance(h2, list) else h2) assert popstrat_var is None or ( popstrat_var >= 0), 'popstrat_var must be non-negative' uid = Env.get_uid(base=100) @@ -669,7 +669,7 @@ def annotate_all(mt, row_exprs={}, col_exprs={}, entry_exprs={}, global_exprs={} r"""Equivalent of _annotate_all, but checks source MatrixTable of exprs""" exprs = {**row_exprs, **col_exprs, **entry_exprs, **global_exprs} for key, value in exprs.items(): - if type(value) == expr_float64 or type(value) == expr_int32: + if value.dtype in (hl.tfloat64, hl.tint32): assert value._indices.source == mt, 'Cannot combine expressions from different source objects.' return mt._annotate_all(row_exprs, col_exprs, entry_exprs, global_exprs) @@ -708,8 +708,8 @@ def agg_fields(tb, coef_dict=None, str_expr=None, axis='rows'): coef_dict = get_coef_dict(tb=tb, str_expr=str_expr, ref_coef_dict=coef_dict, axis=axis) axis_field = 'annot' if axis == 'rows' else 'cov' - annotate_fn = (MatrixTable.annotate_rows if axis == 'rows' else MatrixTable.annotate_cols) if type( - tb) is MatrixTable else Table.annotate + annotate_fn = (MatrixTable.annotate_rows if axis == 'rows' else MatrixTable.annotate_cols + ) if isinstance(tb, MatrixTable) else Table.annotate tb = annotate_fn(self=tb, **{'agg_' + axis_field: 0}) print( f'Fields and associated coefficients used in {axis_field} aggregation: {coef_dict}') @@ -750,8 +750,7 @@ def get_coef_dict(tb, str_expr=None, ref_coef_dict=None, axis='rows'): """ assert (str_expr is not None or ref_coef_dict is not None), "str_expr and ref_coef_dict cannot both be None" assert axis == 'rows' or axis == 'cols', "axis must be 'rows' or 'cols'" - fields_to_search = (tb.row if axis == 'rows' or type(tb) - is Table else tb.col) + fields_to_search = (tb.row if axis == 'rows' or isinstance(tb, Table) else tb.col) # when axis='rows' we're searching for annotations, axis='cols' searching for covariates axis_field = 'annotation' if axis == 'rows' else 'covariate' if str_expr is None: From 57cf14d2f6c7d3d626db6baa511721b56023647f Mon Sep 17 00:00:00 2001 From: iris <84595986+iris-garden@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:18:52 -0400 Subject: [PATCH 133/180] [ci/ui] fixes 500 when there are no jobs to display (#13254) This change sorts the jobs for a PR correctly in the UI, so that all jobs are placed under a header with the correct state (see screenshot). Because jobs are split into separate tables by their state, `focusOnSlash` has been removed from the relevant CI pages, since it is unknown which tables will exist on the page until it is rendered. It also fixes the error that was causing the server to return a 500 when there were no jobs yet (e.g. when a retry had just been requested), which was caused by an assumption in the original job filtering code that there would always be at least one job to display. It also passes the list of developers through to the underlying `PR` object that a `WatchedBranch` has, which was missed in https://github.com/hail-is/hail/pull/13398 but is required for CI to display the PR page correctly in dev deploys only. Screenshot 2023-08-22 at 15 08 48 --- ci/ci/ci.py | 10 +++++++--- ci/ci/github.py | 17 ++++++++++++++++- ci/ci/templates/batch.html | 3 --- ci/ci/templates/filtered-jobs.html | 22 +++++++++------------- ci/ci/templates/pr.html | 3 --- 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/ci/ci/ci.py b/ci/ci/ci.py index d3112d9e6f9..3b3770e98d3 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -152,10 +152,14 @@ def wb_and_pr_from_request(request: web.Request) -> Tuple[WatchedBranch, PR]: def filter_jobs(jobs): - filtered: Dict[str, list] = {"running": [], "failed": [], "pending": [], "jobs": []} + filtered: Dict[str, list] = { + state: [] + # the order of this list is the order in which the states will be displayed on the page + for state in ["failed", "error", "cancelled", "running", "pending", "ready", "creating", "success"] + } for job in jobs: - filtered.get(job["state"].lower(), filtered["jobs"]).append(job) - return {"completed" if k == "jobs" else k: v if len(v) > 0 else None for k, v in filtered.items()} + filtered[job["state"].lower()].append(job) + return {"jobs": filtered} @routes.get('/watched_branches/{watched_branch_index}/pr/{pr_number}') diff --git a/ci/ci/github.py b/ci/ci/github.py index 5e47139a0c6..5df530e3223 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -228,7 +228,18 @@ def clone_or_fetch_script(repo): class PR(Code): def __init__( - self, number, title, body, source_branch, source_sha, target_branch, author, assignees, reviewers, labels + self, + number, + title, + body, + source_branch, + source_sha, + target_branch, + author, + assignees, + reviewers, + labels, + developers, ): self.number: int = number self.title: str = title @@ -258,6 +269,8 @@ def __init__( self.target_branch.batch_changed = True self.target_branch.state_changed = True + self.developers = developers + def set_build_state(self, build_state): log.info(f'{self.short_str()}: Build state changing from {self.build_state} => {build_state}') if build_state != self.build_state: @@ -355,6 +368,7 @@ def from_gh_json(gh_json, target_branch): {user['login'] for user in gh_json['assignees']}, {user['login'] for user in gh_json['requested_reviewers']}, {label['name'] for label in gh_json['labels']}, + target_branch.developers, ) pr.increment_pr_metric() return pr @@ -368,6 +382,7 @@ def config(self): target_repo = self.target_branch.branch.repo return { 'checkout_script': self.checkout_script(), + 'developers': self.developers, 'number': self.number, 'source_repo': source_repo.short_str(), 'source_repo_url': source_repo.url, diff --git a/ci/ci/templates/batch.html b/ci/ci/templates/batch.html index aa305c33822..1b2d6ae75ab 100644 --- a/ci/ci/templates/batch.html +++ b/ci/ci/templates/batch.html @@ -30,7 +30,4 @@

Attributes

Jobs

{{ filtered_jobs(running, failed, pending, completed) }} - {% endblock %} diff --git a/ci/ci/templates/filtered-jobs.html b/ci/ci/templates/filtered-jobs.html index 68600a7a52e..5d12d460abf 100644 --- a/ci/ci/templates/filtered-jobs.html +++ b/ci/ci/templates/filtered-jobs.html @@ -1,17 +1,13 @@ {% from "job-table.html" import job_table with context %} {% macro filtered_jobs(running, failed, pending, completed) %} -{% if failed is not none %} -

Failed

- {{ job_table(failed, "failed-jobs", "failedJobsSearchBar") }} +{% if jobs.items()|length %} + {% for state, state_jobs in jobs.items() %} + {% if state_jobs|length %} +

{{ state.capitalize() }}

+ {{ job_table(state_jobs, "{{ state }}-jobs", "{{ state }}JobsSearchBar") }} + {% endif %} + {% endfor %} +{% else %} +
No jobs found.
{% endif %} -{% if running is not none %} -

Running

- {{ job_table(running, "running-jobs", "runningJobsSearchBar") }} -{% endif %} -{% if pending is not none %} -

Pending

- {{ job_table(pending, "pending-jobs", "pendingJobsSearchBar") }} -{% endif %} -

Completed

-{{ job_table(completed, "completed-jobs", "completedJobsSearchBar") }} {% endmacro %} diff --git a/ci/ci/templates/pr.html b/ci/ci/templates/pr.html index 18b5cd10fa1..97110432a2f 100644 --- a/ci/ci/templates/pr.html +++ b/ci/ci/templates/pr.html @@ -62,7 +62,4 @@

Build History

{% else %} No builds. {% endif %} - {% endblock %} From de7510f9252e1c71033d1914fd4b20a041f38d24 Mon Sep 17 00:00:00 2001 From: Dan King Date: Wed, 23 Aug 2023 12:40:49 -0400 Subject: [PATCH 134/180] [query] frozenlist.__repr__ should be eval-able (#13422) CHANGELOG: Hail `frozenlist` now has an eval-able `repr`. `hailtop.hail_frozenlist.frozenlist` previously inherited the `repr` of the `frozenlist` library: > frozenlist([1, 2, 3]) With this change, I both use the fact that `frozen=True` for Hail frozenlists and use a printed form that is actually eval-able: > frozenlist([1, 2, 3]) frozenlist([1, 2, 3]) > eval(repr(frozenlist([1, 2, 3]))) frozenlist([1, 2, 3]) --- hail/python/hailtop/hail_frozenlist.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hail/python/hailtop/hail_frozenlist.py b/hail/python/hailtop/hail_frozenlist.py index ef6c8ab9f2f..3d5da29bd92 100644 --- a/hail/python/hailtop/hail_frozenlist.py +++ b/hail/python/hailtop/hail_frozenlist.py @@ -9,3 +9,6 @@ class frozenlist(_FrozenList, Sequence[T]): def __init__(self, items: List[T]): super().__init__(items) self.freeze() + + def __repr__(self) -> str: + return f'frozenlist({list(self)})' From 1391db082a94010d4e0b3413b62e0096996190e9 Mon Sep 17 00:00:00 2001 From: jigold Date: Wed, 23 Aug 2023 16:34:21 -0400 Subject: [PATCH 135/180] [hailctl] Initialize Hail Environment Interactively (#13279) I wanted to get feedback on the code I've written thus far before I start testing everything. I'm worried it might be too complicated / brittle to maintain. I also chose to blow away the entire existing environment rather than resetting the variables with new values. Not sure if that's what we want. --- hail/python/hailtop/auth/__init__.py | 7 +- hail/python/hailtop/auth/tokens.py | 25 +- hail/python/hailtop/hailctl/batch/cli.py | 8 + .../hailtop/hailctl/batch/initialize.py | 252 ++++++++++++++++++ hail/python/hailtop/hailctl/batch/utils.py | 142 ++++++++++ 5 files changed, 423 insertions(+), 11 deletions(-) create mode 100644 hail/python/hailtop/hailctl/batch/initialize.py create mode 100644 hail/python/hailtop/hailctl/batch/utils.py diff --git a/hail/python/hailtop/auth/__init__.py b/hail/python/hailtop/auth/__init__.py index 84d07757c10..378eee1c576 100644 --- a/hail/python/hailtop/auth/__init__.py +++ b/hail/python/hailtop/auth/__init__.py @@ -1,16 +1,19 @@ from . import sql_config -from .tokens import (get_tokens, session_id_encode_to_str, +from .tokens import (NotLoggedInError, get_tokens, session_id_encode_to_str, session_id_decode_from_str) from .auth import ( get_userinfo, hail_credentials, copy_paste_login, async_copy_paste_login, - async_create_user, async_delete_user, async_get_user, async_logout) + async_create_user, async_delete_user, async_get_user, async_logout, + async_get_userinfo) __all__ = [ + 'NotLoggedInError', 'get_tokens', 'async_create_user', 'async_delete_user', 'async_get_user', + 'async_get_userinfo', 'get_userinfo', 'hail_credentials', 'async_copy_paste_login', diff --git a/hail/python/hailtop/auth/tokens.py b/hail/python/hailtop/auth/tokens.py index 0e45a89fc25..516bfa94499 100644 --- a/hail/python/hailtop/auth/tokens.py +++ b/hail/python/hailtop/auth/tokens.py @@ -2,7 +2,6 @@ import base64 import collections.abc import os -import sys import json import logging from hailtop.config import get_deploy_config @@ -19,6 +18,21 @@ def session_id_decode_from_str(session_id_str: str) -> bytes: return base64.urlsafe_b64decode(session_id_str.encode('ascii')) +class NotLoggedInError(Exception): + def __init__(self, ns_arg): + super().__init__() + self.message = f''' +You are not authenticated. Please log in with: + + $ hailctl auth login {ns_arg} + +to obtain new credentials. +''' + + def __str__(self): + return self.message + + class Tokens(collections.abc.MutableMapping): @staticmethod def get_tokens_file() -> str: @@ -61,14 +75,7 @@ def namespace_token_or_error(self, ns: str) -> str: deploy_config = get_deploy_config() auth_ns = deploy_config.service_ns('auth') ns_arg = '' if ns == auth_ns else f'-n {ns}' - sys.stderr.write(f'''\ -You are not authenticated. Please log in with: - - $ hailctl auth login {ns_arg} - -to obtain new credentials. -''') - sys.exit(1) + raise NotLoggedInError(ns_arg) def __delitem__(self, key: str): del self._tokens[key] diff --git a/hail/python/hailtop/hailctl/batch/cli.py b/hail/python/hailtop/hailctl/batch/cli.py index 841cd63e94f..e33e4299367 100644 --- a/hail/python/hailtop/hailctl/batch/cli.py +++ b/hail/python/hailtop/hailctl/batch/cli.py @@ -8,6 +8,7 @@ from . import list_batches from . import billing +from .initialize import async_basic_initialize from . import submit as _submit from .batch_cli_utils import ( get_batch_if_exists, @@ -170,3 +171,10 @@ def submit( $ hailctl batch submit --image-name docker.io/image my_script.py -- some-argument --animal dog ''' asyncio.run(_submit.submit(name, image_name, files or [], output, script, [*(arguments or []), *ctx.args])) + + +@app.command('init', help='Initialize a Hail Batch environment.') +def initialize( + verbose: Ann[bool, Opt('--verbose', '-v', help='Print gcloud commands being executed')] = False +): + asyncio.get_event_loop().run_until_complete(async_basic_initialize(verbose=verbose)) diff --git a/hail/python/hailtop/hailctl/batch/initialize.py b/hail/python/hailtop/hailctl/batch/initialize.py new file mode 100644 index 00000000000..8f22cdfffd9 --- /dev/null +++ b/hail/python/hailtop/hailctl/batch/initialize.py @@ -0,0 +1,252 @@ +from typing import List, Optional, Tuple +import typer + +from typer import Abort, Exit +from rich.prompt import Confirm, IntPrompt, Prompt + +from hailtop.config import ConfigVariable + + +async def setup_existing_remote_tmpdir(service_account: str, verbose: bool) -> Tuple[Optional[str], str, bool]: + from hailtop.aiogoogle import GoogleStorageAsyncFS # pylint: disable=import-outside-toplevel + + from .utils import InsufficientPermissions, get_gcp_bucket_information, grant_service_account_bucket_access_with_role # pylint: disable=import-outside-toplevel + + warnings = False + + remote_tmpdir = Prompt.ask('Enter a path to an existing remote temporary directory (ex: gs://my-bucket/batch/tmp)') + + bucket, _ = GoogleStorageAsyncFS.get_bucket_and_name(remote_tmpdir) + + try: + bucket_info = await get_gcp_bucket_information(bucket, verbose) + except InsufficientPermissions as e: + typer.secho(e.message, fg=typer.colors.RED) + raise Abort() from e + + location = bucket_info['location'].lower() + + if bucket_info['locationType'] != 'region': + typer.secho(f'WARNING: remote temporary directory {remote_tmpdir} is multi-regional. Using this bucket with the Batch Service will incur additional network fees.', + fg=typer.colors.YELLOW) + warnings = True + + storage_class = bucket_info['storageClass'] + if storage_class.upper() != 'STANDARD': + typer.secho(f'WARNING: remote temporary directory {remote_tmpdir} does not have storage class "STANDARD". Additional data recovery charges will occur when accessing data.', + fg=typer.colors.YELLOW) + warnings = True + + give_access_to_remote_tmpdir = Confirm.ask(f'Do you want to give service account {service_account} read/write access to bucket {bucket}?') + if give_access_to_remote_tmpdir: + try: + await grant_service_account_bucket_access_with_role(bucket=bucket, service_account=service_account, role= 'roles/storage.objectViewer', verbose=verbose) + await grant_service_account_bucket_access_with_role(bucket=bucket, service_account=service_account, role= 'roles/storage.objectCreator', verbose=verbose) + except InsufficientPermissions as e: + typer.secho(e.message, fg=typer.colors.RED) + raise Abort() from e + typer.secho(f'Granted service account {service_account} read and write access to {bucket}.', fg=typer.colors.GREEN) + else: + typer.secho(f'WARNING: Please verify service account {service_account} has the role "roles/storage.objectAdmin" or ' + f'both "roles/storage.objectViewer" and "roles/storage.objectCreator" roles for bucket {bucket}.', + fg=typer.colors.YELLOW) + warnings = True + + return (remote_tmpdir, location, warnings) + + +async def setup_new_remote_tmpdir(*, + supported_regions: List[str], + username: str, + service_account: str, + verbose: bool) -> Tuple[Optional[str], str, bool]: + from hailtop.utils import secret_alnum_string # pylint: disable=import-outside-toplevel + + from .utils import BucketAlreadyExistsError, InsufficientPermissions, create_gcp_bucket, \ + get_gcp_default_project, grant_service_account_bucket_access_with_role, update_gcp_bucket # pylint: disable=import-outside-toplevel + + token = secret_alnum_string(5).lower() + maybe_bucket_name = f'hail-batch-{username}-{token}' + bucket_name = Prompt.ask(f'What is the name of the new bucket (Example: {maybe_bucket_name})') + + default_project = await get_gcp_default_project(verbose=verbose) + bucket_prompt = f'Which google project should {bucket_name} be created in? This project will incur costs for storing your Hail generated data.' + if default_project is not None: + bucket_prompt += f' (Example: {default_project})' + project = Prompt.ask(bucket_prompt) + + if 'us-central1' in supported_regions: + default_compute_region = 'us-central1' + else: + default_compute_region = supported_regions[0] + + bucket_region = Prompt.ask(f'Which region does your data reside in? (Example: {default_compute_region})') + if bucket_region not in supported_regions: + typer.secho(f'The region where your data lives ({bucket_region}) is not in one of the supported regions of the Batch Service ({supported_regions}). ' + f'Creating a bucket in {bucket_region} will incur additional network fees when using the Batch Service.', fg=typer.colors.YELLOW) + continue_w_region_error = Confirm.ask(f'Do you wish to continue setting up the new bucket {bucket_name} in region {bucket_region}?') + if not continue_w_region_error: + raise Abort() + + remote_tmpdir = f'gs://{bucket_name}/batch/tmp' + warnings = False + + set_lifecycle = Confirm.ask( + f'Do you want to set a lifecycle policy (automatically delete files after a time period) on the bucket {bucket_name}?') + if set_lifecycle: + lifecycle_days = IntPrompt.ask( + f'After how many days should files be automatically deleted from bucket {bucket_name}?', default=30) + if lifecycle_days <= 0: + typer.secho(f'Invalid value for lifecycle rule in days {lifecycle_days}', fg=typer.colors.RED) + raise Abort() + else: + lifecycle_days = None + + labels = { + 'bucket': bucket_name, + 'owner': username, + 'data_type': 'temporary', + } + + try: + await create_gcp_bucket( + project=project, + bucket=bucket_name, + location=bucket_region, + verbose=verbose, + ) + typer.secho(f'Created bucket {bucket_name} in project {project}.', fg=typer.colors.GREEN) + except InsufficientPermissions as e: + typer.secho(e.message, fg=typer.colors.RED) + raise Abort() from e + except BucketAlreadyExistsError as e: + typer.secho(e.message, fg=typer.colors.YELLOW) + continue_w_update = Confirm.ask(f'Do you wish to continue updating the lifecycle rules and permissions on bucket {bucket_name}?') + if not continue_w_update: + typer.secho(f'WARNING: The lifecycle rules and permissions on bucket {bucket_name} were not updated. ' + 'You will have to manually configure these yourself.', fg=typer.colors.YELLOW) + warnings = True + return (remote_tmpdir, bucket_region, warnings) + + try: + await update_gcp_bucket( + project=project, + bucket=bucket_name, + lifecycle_days=lifecycle_days, + labels=labels, + verbose=verbose, + ) + except InsufficientPermissions as e: + typer.secho(e.message, fg=typer.colors.RED) + raise Abort() from e + + typer.secho(f'Updated bucket {bucket_name} in project {project} with lifecycle rule set to {lifecycle_days} days and labels {labels}.', fg=typer.colors.GREEN) + + try: + await grant_service_account_bucket_access_with_role(bucket_name, service_account, 'roles/storage.objectViewer', verbose=verbose) + await grant_service_account_bucket_access_with_role(bucket_name, service_account, 'roles/storage.objectCreator', verbose=verbose) + except InsufficientPermissions as e: + typer.secho(e.message, fg=typer.colors.RED) + raise Abort() from e + + typer.secho(f'Granted service account {service_account} read and write access to {bucket_name} in project {project}.', + fg=typer.colors.GREEN) + + return (remote_tmpdir, bucket_region, warnings) + + +async def initialize_gcp(username: str, + hail_identity: str, + supported_regions: List[str], + verbose: bool) -> Tuple[Optional[str], str, bool]: + from .utils import check_for_gcloud # pylint: disable=import-outside-toplevel + assert len(supported_regions) > 0 + + gcloud_installed = await check_for_gcloud() + if not gcloud_installed: + typer.secho('Have you installed gcloud? For directions see https://cloud.google.com/sdk/docs/install ' + 'To log into gcloud run:\n' + '> gcloud auth application-default login', + fg=typer.colors.RED) + raise Abort() + + create_remote_tmpdir = Confirm.ask('Do you want to create a new bucket for temporary files generated by Hail?') + if create_remote_tmpdir: + remote_tmpdir, location, warnings = await setup_new_remote_tmpdir( + supported_regions=supported_regions, + username=username, + service_account=hail_identity, + verbose=verbose, + ) + else: + remote_tmpdir, location, warnings = await setup_existing_remote_tmpdir(hail_identity, verbose) + + return (remote_tmpdir, location, warnings) + + +async def async_basic_initialize(verbose: bool = False): + from hailtop.auth import async_get_userinfo # pylint: disable=import-outside-toplevel + from hailtop.batch_client.aioclient import BatchClient # pylint: disable=import-outside-toplevel + from hailtop.config.deploy_config import get_deploy_config # pylint: disable=import-outside-toplevel + from hailtop.hailctl.config.cli import set as set_config, list as list_config # pylint: disable=import-outside-toplevel + + from .utils import already_logged_into_service, login_to_service # pylint: disable=import-outside-toplevel + + already_logged_in = await already_logged_into_service() + if not already_logged_in: + typer.secho('You are not currently logged in to Hail. Redirecting you to a login screen.', fg=typer.colors.YELLOW) + await login_to_service() + typer.secho('In the future, you can use `hailctl auth login` to login to Hail.', fg=typer.colors.YELLOW) + else: + domain = get_deploy_config()._domain + typer.secho(f'You are currently logged in to Hail at domain {domain}.') + + user_info = await async_get_userinfo() + username = user_info['username'] + hail_identity = user_info['hail_identity'] + trial_bp_name = user_info['trial_bp_name'] + + batch_client = await BatchClient.create(trial_bp_name) + + async with batch_client: + cloud = await batch_client.cloud() + supported_regions = await batch_client.supported_regions() + + if cloud == 'gcp': + remote_tmpdir, tmpdir_region, warnings = await initialize_gcp(username, hail_identity, supported_regions, verbose) + else: + remote_tmpdir = Prompt.ask('Enter a path to an existing remote temporary directory (ex: https://myaccount.blob.core.windows.net/mycontainer/batch/tmp)') + typer.secho(f'WARNING: You will need to grant read/write access to {remote_tmpdir} for account {hail_identity}', fg=typer.colors.YELLOW) + warnings = False + + tmpdir_region = Prompt.ask('Which region is your remote temporary directory in? (Example: eastus)') + + compute_region = Prompt.ask('Which region do you want your jobs to run in?', choices=supported_regions) + + if tmpdir_region != compute_region and not compute_region.startswith(tmpdir_region): + typer.secho(f'WARNING: remote temporary directory "{remote_tmpdir}" is not located in the selected compute region for Batch jobs "{compute_region}". Found {tmpdir_region}.', + fg=typer.colors.YELLOW) + warnings = True + + if trial_bp_name: + set_config(ConfigVariable.BATCH_BILLING_PROJECT, trial_bp_name) + + if remote_tmpdir: + set_config(ConfigVariable.BATCH_REMOTE_TMPDIR, remote_tmpdir) + + set_config(ConfigVariable.BATCH_REGIONS, compute_region) + + set_config(ConfigVariable.BATCH_BACKEND, 'service') + + query_backend = Prompt.ask('Which backend do you want to use for Hail Query?', choices=['spark', 'batch', 'local']) + set_config(ConfigVariable.QUERY_BACKEND, query_backend) + + typer.secho('--------------------', fg=typer.colors.BLUE) + typer.secho('FINAL CONFIGURATION:', fg=typer.colors.BLUE) + typer.secho('--------------------', fg=typer.colors.BLUE) + list_config() + + if warnings: + typer.secho('WARNING: The currently specified configuration will result in additional fees when using Hail Batch.', + fg=typer.colors.YELLOW) + raise Exit() diff --git a/hail/python/hailtop/hailctl/batch/utils.py b/hail/python/hailtop/hailctl/batch/utils.py new file mode 100644 index 00000000000..8adb709c75a --- /dev/null +++ b/hail/python/hailtop/hailctl/batch/utils.py @@ -0,0 +1,142 @@ +import json +import tempfile +from typing import Dict, Optional + + +class InsufficientPermissions(Exception): + def __init__(self, message: str): + self.message = message + + +class BucketAlreadyExistsError(Exception): + def __init__(self, message: str): + self.message = message + + +async def already_logged_into_service() -> bool: + from hailtop.auth import NotLoggedInError, async_get_userinfo # pylint: disable=import-outside-toplevel + + try: + await async_get_userinfo() + return True + except NotLoggedInError: + return False + + +async def login_to_service(): + from hailtop.hailctl.auth.login import async_login # pylint: disable=import-outside-toplevel + await async_login('default') + + +async def check_for_gcloud() -> bool: + from hailtop.utils import check_exec_output # pylint: disable=import-outside-toplevel + try: + await check_exec_output('gcloud', 'version') + return True + except Exception: + return False + + +async def get_gcp_default_project(verbose: bool) -> Optional[str]: + from hailtop.utils import check_exec_output # pylint: disable=import-outside-toplevel + try: + project, _ = await check_exec_output('gcloud', 'config', 'get-value', 'project', echo=verbose) + project_str = project.strip().decode('utf-8') + return project_str + except Exception: + return None + + +async def get_gcp_bucket_information(bucket: str, verbose: bool) -> dict: + from hailtop.utils import CalledProcessError, check_exec_output # pylint: disable=import-outside-toplevel + try: + info, _ = await check_exec_output('gcloud', 'storage', 'buckets', 'describe', f'gs://{bucket}', '--format="json"', echo=verbose) + return json.loads(info.decode('utf-8')) + except CalledProcessError as e: + if 'does not have storage.buckets.get access to the Google Cloud Storage bucket' in e.stderr.decode('utf-8'): + msg = f'ERROR: You do not have sufficient permissions to get information about bucket {bucket} or it does not exist. ' \ + f'If the bucket exists, ask a project administrator to give you the permission "storage.buckets.get" or ' \ + f'assign you the StorageAdmin role in Google Cloud Storage.' + raise InsufficientPermissions(msg) from e + raise + + +async def create_gcp_bucket(*, + project: str, + bucket: str, + location: str, + verbose: bool): + from hailtop.utils import CalledProcessError, check_exec_output # pylint: disable=import-outside-toplevel + + try: + await check_exec_output('gcloud', '--project', project, 'storage', 'buckets', 'create', f'gs://{bucket}', f'--location={location}', echo=verbose) + except CalledProcessError as e: + if 'does not have storage.buckets.create access to the Google Cloud project' in e.stderr.decode('utf-8'): + msg = f'ERROR: You do not have the necessary permissions to create buckets in project {project}. Ask a project administrator ' \ + f'to give you the permission "storage.buckets.create" or assign you the StorageAdmin role or ask them to create the bucket {bucket} on your behalf.' + raise InsufficientPermissions(msg) from e + if 'Your previous request to create the named bucket succeeded and you already own it' in e.stderr.decode('utf-8'): + msg = f'WARNING: Bucket {bucket} was previously created.' + raise BucketAlreadyExistsError(msg) from e + raise + + +async def update_gcp_bucket(*, + project: str, + bucket: str, + lifecycle_days: Optional[int], + labels: Optional[Dict[str, str]], + verbose: bool): + from hailtop.utils import CalledProcessError, check_exec_output # pylint: disable=import-outside-toplevel + + if labels: + labels_str = ','.join(f'{k}={v}' for k, v in labels.items()) + else: + labels_str = None + + try: + if lifecycle_days: + lifecycle_policy = { + "rule": [ + { + "action": {"type": "Delete"}, + "condition": {"age": lifecycle_days} + } + ] + } + + with tempfile.NamedTemporaryFile(mode='w') as f: + f.write(json.dumps(lifecycle_policy)) + f.flush() + await check_exec_output('gcloud', '--project', project, 'storage', 'buckets', 'update', + f'--lifecycle-file={f.name}', f'gs://{bucket}', echo=verbose) + + if labels_str: + await check_exec_output('gcloud', '--project', project, 'storage', 'buckets', 'update', + f'--update-labels={labels_str}', f'gs://{bucket}', echo=verbose) + except CalledProcessError as e: + if 'does not have storage.buckets.get access to the Google Cloud Storage bucket' in e.stderr.decode('utf-8'): + msg = f'ERROR: You do not have the necessary permissions to update bucket {bucket} in project {project}. Ask a project administrator ' \ + f'to assign you the StorageAdmin role in Google Cloud Storage for bucket {bucket} or ask them to update the bucket {bucket} on your behalf.' + if lifecycle_days: + msg += f'Update the bucket to have a lifecycle policy of {lifecycle_days} days.' + if labels_str: + msg += f'Update the bucket to have labels: {labels_str}' + raise InsufficientPermissions(msg) from e + raise + + +async def grant_service_account_bucket_access_with_role(bucket: str, service_account: str, role: str, verbose: bool): + from hailtop.utils import CalledProcessError, check_exec_output # pylint: disable=import-outside-toplevel + + try: + service_account_member = f'serviceAccount:{service_account}' + await check_exec_output('gcloud', 'storage', 'buckets', 'add-iam-policy-binding', f'gs://{bucket}', '--member', service_account_member, '--role', role, + echo=verbose) + except CalledProcessError as e: + if 'does not have storage.buckets.getIamPolicy access to the Google Cloud Storage bucket' in e.stderr.decode('utf-8'): + msg = f'ERROR: You do not have the necessary permissions to set permissions for bucket {bucket}. Ask a project administrator ' \ + f'to assign you the StorageIAMAdmin role in Google Cloud Storage or ask them to update the permissions on your behalf by giving ' \ + f'service account {service_account} the role "{role}" for bucket {bucket}.' + raise InsufficientPermissions(msg) from e + raise From 8be7118f062df1d5cc7a50037a3110ad978d5011 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 23 Aug 2023 17:44:49 -0400 Subject: [PATCH 136/180] [aiotools] Log exception is task manager task errors (#13453) --- hail/python/hailtop/aiotools/tasks.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/hail/python/hailtop/aiotools/tasks.py b/hail/python/hailtop/aiotools/tasks.py index 74d6cfcc498..57c39b731bf 100644 --- a/hail/python/hailtop/aiotools/tasks.py +++ b/hail/python/hailtop/aiotools/tasks.py @@ -1,4 +1,4 @@ -from typing import Set +from typing import Callable, Set import asyncio import logging @@ -21,9 +21,20 @@ def ensure_future(self, coroutine): if self._closed: raise TaskManagerClosedError t = asyncio.create_task(coroutine) - t.add_done_callback(lambda _: self.tasks.remove(t)) + t.add_done_callback(self.on_task_done(t)) self.tasks.add(t) + def on_task_done(self, t: asyncio.Task) -> Callable[[asyncio.Future], None]: + def callback(fut: asyncio.Future): + self.tasks.remove(t) + try: + if e := fut.exception(): + log.exception(e) + except asyncio.CancelledError: + if not self._closed: + log.exception('Background task was cancelled before task manager shutdown') + return callback + def shutdown(self): self._closed = True for task in self.tasks: From 90886da936f797f1dc7f06b662689b71771b663a Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Wed, 23 Aug 2023 19:24:19 -0400 Subject: [PATCH 137/180] [query] Add bounds checks to local_to_global (#13485) Make sure that all local alleles are less than the n_total_alleles parameter passed to the function. This error will often occur if a vds is split with regular split_multi rather than vds.split_multi Closes #13479 --- hail/python/test/hail/vds/test_vds_functions.py | 13 +++++++++++++ .../is/hail/expr/ir/functions/ArrayFunctions.scala | 2 ++ 2 files changed, 15 insertions(+) diff --git a/hail/python/test/hail/vds/test_vds_functions.py b/hail/python/test/hail/vds/test_vds_functions.py index dc4b0a4859d..831f792e134 100644 --- a/hail/python/test/hail/vds/test_vds_functions.py +++ b/hail/python/test/hail/vds/test_vds_functions.py @@ -1,3 +1,5 @@ +import pytest + import hail as hl def test_lgt_to_gt(): @@ -49,3 +51,14 @@ def test_local_to_global_missing_fill(): local_alleles = [0, 3, 1] lad = [1, 10, 9] assert hl.eval(hl.vds.local_to_global(lad, local_alleles, 4, hl.missing('int32'), number='R')) == [1, 9, None, 10] + +def test_local_to_global_out_of_bounds(): + local_alleles = [0, 2] + lad = [1, 9] + lpl = [1001, 0, 1002] + + with pytest.raises(hl.utils.HailUserError, match='local_to_global: local allele of 2 out of bounds given n_total_alleles of 2'): + assert hl.eval(hl.vds.local_to_global(lad, local_alleles, 2, 0, number='R')) == [1, 0] + + with pytest.raises(hl.utils.HailUserError, match='local_to_global: local allele of 2 out of bounds given n_total_alleles of 2'): + assert hl.eval(hl.vds.local_to_global(lpl, local_alleles, 2, 10001, number='G')) == [1001, 10001, 0, 10001, 10001, 1002] diff --git a/hail/src/main/scala/is/hail/expr/ir/functions/ArrayFunctions.scala b/hail/src/main/scala/is/hail/expr/ir/functions/ArrayFunctions.scala index 703d09683d8..0b4507a9f46 100644 --- a/hail/src/main/scala/is/hail/expr/ir/functions/ArrayFunctions.scala +++ b/hail/src/main/scala/is/hail/expr/ir/functions/ArrayFunctions.scala @@ -355,6 +355,7 @@ object ArrayFunctions extends RegistryFunctions { val laGIndexer = cb.newLocal[Int]("g_indexer", 0) cb.whileLoop(i < laLen, { val lai = localAlleles.loadElement(cb, i).get(cb, "local_to_global: local alleles elements cannot be missing", err).asInt32.value + cb.ifx(lai >= nTotalAlleles, cb._fatalWithError(err, "local_to_global: local allele of ", lai.toS, " out of bounds given n_total_alleles of ", nTotalAlleles.toS)) val j = cb.newLocal[Int]("la_j", 0) cb.whileLoop(j <= i, { @@ -414,6 +415,7 @@ object ArrayFunctions extends RegistryFunctions { val i = cb.newLocal[Int]("la_i", 0) cb.whileLoop(i < localLen, { val lai = localAlleles.loadElement(cb, i + idxAdjustmentForOmitFirst).get(cb, "local_to_global: local alleles elements cannot be missing", err).asInt32.value + cb.ifx(lai >= nTotalAlleles, cb._fatalWithError(err, "local_to_global: local allele of ", lai.toS, " out of bounds given n_total_alleles of ", nTotalAlleles.toS)) push(cb, cb.memoize(lai - idxAdjustmentForOmitFirst), array.loadElement(cb, i)) cb.assign(i, i + 1) From 2ca85a69340c3fab95519aeae8e140507d62613f Mon Sep 17 00:00:00 2001 From: jigold Date: Wed, 23 Aug 2023 22:29:54 -0400 Subject: [PATCH 138/180] [ci] Choose order for testing PRs by merge priority order (#13478) --- ci/ci/github.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ci/ci/github.py b/ci/ci/github.py index 5df530e3223..747f3f75721 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -920,7 +920,9 @@ async def _heal(self, app, batch_client, gh): self.n_running_batches = sum(1 for pr in self.prs.values() if pr.batch and not pr.build_state) - for pr in self.prs.values(): + prs_by_prio = sorted(self.prs.values(), key=lambda pr: pr.merge_priority(), reverse=True) + + for pr in prs_by_prio: await pr._heal(batch_client, db, pr == merge_candidate, gh) # cancel orphan builds From 7ff68326ebfdca631ab3af112027b3e1debe85bc Mon Sep 17 00:00:00 2001 From: iris <84595986+iris-garden@users.noreply.github.com> Date: Thu, 24 Aug 2023 14:59:08 -0400 Subject: [PATCH 139/180] [batch/ui] adds advanced search box and help link (#13463) The updated template renders the following in Firefox on my machine: Screenshot 2023-08-18 at 19 56 27 --- batch/batch/front_end/query/__init__.py | 2 +- batch/batch/front_end/templates/batch.html | 42 +----------- batch/batch/front_end/templates/batches.html | 46 +------------ .../front_end/templates/table_search.html | 67 +++++++++++++++++++ 4 files changed, 72 insertions(+), 85 deletions(-) create mode 100644 batch/batch/front_end/templates/table_search.html diff --git a/batch/batch/front_end/query/__init__.py b/batch/batch/front_end/query/__init__.py index c995cc378b3..5f1e45f7f82 100644 --- a/batch/batch/front_end/query/__init__.py +++ b/batch/batch/front_end/query/__init__.py @@ -1,7 +1,7 @@ from .query_v1 import parse_batch_jobs_query_v1, parse_list_batches_query_v1 from .query_v2 import parse_batch_jobs_query_v2, parse_list_batches_query_v2 -CURRENT_QUERY_VERSION = 1 +CURRENT_QUERY_VERSION = 2 __all__ = [ 'CURRENT_QUERY_VERSION', diff --git a/batch/batch/front_end/templates/batch.html b/batch/batch/front_end/templates/batch.html index 4bb15afddf2..817260f4aaf 100644 --- a/batch/batch/front_end/templates/batch.html +++ b/batch/batch/front_end/templates/batch.html @@ -1,3 +1,4 @@ +{% from "table_search.html" import table_search with context %} {% extends "layout.html" %} {% block title %}Batch {{ batch['id'] }}{% endblock %} {% block head %} @@ -43,43 +44,7 @@

Attributes

Jobs

-
-
- - - - - -
-

Search jobs with the given search terms. Return jobs - that match all terms. Terms:

-
    -
  • job_id=JOB_ID - jobs with an id equal to JOB_ID
  • -
  • k=v - jobs with an attribute with key k and value v
  • -
  • has:k - jobs that have an attribute with key k
  • -
  • state - jobs in the given state, one of: -
      -
    • ready
    • -
    • running
    • -
    • live (ready or running)
    • -
    • cancelled
    • -
    • error
    • -
    • failed
    • -
    • bad (error or failed)
    • -
    • success
    • -
    • done (cancelled, error, failed or success)
    • -
    -
  • -
  • !term - jobs not matched by term
  • -
-
-
+ {{ table_search("job-search", base_path ~ "/batches/" ~ batch["id"]) }}
@@ -134,7 +99,4 @@

Jobs

{% endif %} - {% endblock %} diff --git a/batch/batch/front_end/templates/batches.html b/batch/batch/front_end/templates/batches.html index d657a59d094..f30d4fe7589 100644 --- a/batch/batch/front_end/templates/batches.html +++ b/batch/batch/front_end/templates/batches.html @@ -1,3 +1,4 @@ +{% from "table_search.html" import table_search with context %} {% extends "layout.html" %} {% block title %}Batches{% endblock %} {% block head %} @@ -6,47 +7,7 @@ {% block content %}

Batches

-
-
- - - - - -
-

Search batches with the given search terms. Return batches - that match all terms. Terms:

-
    -
  • k=v - batches with an attribute with key k and value v
  • -
  • has:k - batches that have an attribute with key k
  • -
  • user:u - batches that were created by user u
  • -
  • billing_project:bp - batches that were created in billing - project bp
  • -
  • state - batches in the given state, one of: -
      -
    • open
    • -
    • closed (not open)
    • -
    • running
    • -
    • cancelled
    • -
    • failure
    • -
    • success
    • -
    • complete
    • -
    -

    Note: cancelled and failure do not imply complete. - cancelled means cancel has been called. failure means - one (or more) jobs have failed. In either case, the - batch may still be running.

    -
  • -
  • !term - batches not matched by term
  • -
-
-
+ {{ table_search("batch-search", base_path ~ "/batches") }}
@@ -143,7 +104,4 @@

Batches

{% endif %} - {% endblock %} diff --git a/batch/batch/front_end/templates/table_search.html b/batch/batch/front_end/templates/table_search.html new file mode 100644 index 00000000000..2b3f0e9425b --- /dev/null +++ b/batch/batch/front_end/templates/table_search.html @@ -0,0 +1,67 @@ +{% macro table_search(component_name, endpoint) %} + +
+
+
+
+
+ +
+
+ + + + + +
+
+ +
+
+{% endmacro %} From 6c15ea3a6f768e493c7ff6f75f26f1026caafc9b Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 24 Aug 2023 16:45:58 -0400 Subject: [PATCH 140/180] [batch] report unclosed ClientSession alloc location in batch-driver (#13421) We get a lot of spurious Grafana alerts because batch-driver has unclosed `aiohttp.ClientSession` objects. `aiohttp` can [report the creation location](https://github.com/aio-libs/aiohttp/blob/master/aiohttp/client.py#L242-L247), but only when aysncio is in debug mode. I am hesitant to enable debug mode because I suspect it will slow down everything by grabbing stack traces for every coroutine (so that it can report an error later). I adapted the code from the linked asyncio code and tested it as follows: ``` In [1]: import aiohttp ...: import traceback ...: import sys ...: ...: oldinit = aiohttp.ClientSession.__init__ ...: def newinit(self, *args, **kwargs): ...: oldinit(self, *args, **kwargs) ...: self._source_traceback: Optional[ ...: traceback.StackSummary ...: ] = traceback.extract_stack(sys._getframe(1)) ...: aiohttp.ClientSession.__init__ = newinit In [2]: aiohttp.ClientSession() :7: DeprecationWarning: The object should be created within an async function oldinit(self, *args, **kwargs) Out[2]: In [3]: aiohttp.ClientSession() :7: DeprecationWarning: The object should be created within an async function oldinit(self, *args, **kwargs) Out[3]: In [4]: aiohttp.ClientSession() :7: DeprecationWarning: The object should be created within an async function oldinit(self, *args, **kwargs) Out[4]: In [5]: Do you really want to exit ([y]/n)? y Unclosed client session client_session: source_traceback: Object created at (most recent call last): File "/Users/dking/miniconda3/bin/ipython", line 8, in sys.exit(start_ipython()) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/__init__.py", line 128, in start_ipython return launch_new_instance(argv=argv, **kwargs) File "/Users/dking/miniconda3/lib/python3.10/site-packages/traitlets/config/application.py", line 1043, in launch_instance app.start() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/ipapp.py", line 318, in start self.shell.mainloop() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py", line 888, in mainloop self.interact() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py", line 881, in interact self.run_cell(code, store_history=True) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3009, in run_cell result = self._run_cell( File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3064, in _run_cell result = runner(coro) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/async_helpers.py", line 129, in _pseudo_sync_runner coro.send(None) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3269, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3448, in run_ast_nodes if await self.run_code(code, result, async_=asy): File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3508, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "", line 1, in aiohttp.ClientSession() Unclosed client session client_session: source_traceback: Object created at (most recent call last): File "/Users/dking/miniconda3/bin/ipython", line 8, in sys.exit(start_ipython()) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/__init__.py", line 128, in start_ipython return launch_new_instance(argv=argv, **kwargs) File "/Users/dking/miniconda3/lib/python3.10/site-packages/traitlets/config/application.py", line 1043, in launch_instance app.start() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/ipapp.py", line 318, in start self.shell.mainloop() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py", line 888, in mainloop self.interact() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py", line 881, in interact self.run_cell(code, store_history=True) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3009, in run_cell result = self._run_cell( File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3064, in _run_cell result = runner(coro) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/async_helpers.py", line 129, in _pseudo_sync_runner coro.send(None) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3269, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3448, in run_ast_nodes if await self.run_code(code, result, async_=asy): File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3508, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "", line 1, in aiohttp.ClientSession() Unclosed client session client_session: source_traceback: Object created at (most recent call last): File "/Users/dking/miniconda3/bin/ipython", line 8, in sys.exit(start_ipython()) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/__init__.py", line 128, in start_ipython return launch_new_instance(argv=argv, **kwargs) File "/Users/dking/miniconda3/lib/python3.10/site-packages/traitlets/config/application.py", line 1043, in launch_instance app.start() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/ipapp.py", line 318, in start self.shell.mainloop() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py", line 888, in mainloop self.interact() File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py", line 881, in interact self.run_cell(code, store_history=True) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3009, in run_cell result = self._run_cell( File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3064, in _run_cell result = runner(coro) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/async_helpers.py", line 129, in _pseudo_sync_runner coro.send(None) File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3269, in run_cell_async has_raised = await self.run_ast_nodes(code_ast.body, cell_name, File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3448, in run_ast_nodes if await self.run_code(code, result, async_=asy): File "/Users/dking/miniconda3/lib/python3.10/site-packages/IPython/core/interactiveshell.py", line 3508, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "", line 1, in aiohttp.ClientSession() ``` Without the monkey path we only see: ``` Unclosed client session client_session: Unclosed client session client_session: Unclosed client session client_session: ``` --- batch/batch/driver/__main__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/batch/batch/driver/__main__.py b/batch/batch/driver/__main__.py index fb3beb5dcf0..b114f285a57 100644 --- a/batch/batch/driver/__main__.py +++ b/batch/batch/driver/__main__.py @@ -3,6 +3,22 @@ # configure logging before importing anything else configure_logging() +import sys # noqa: E402 pylint: disable=wrong-import-position +import traceback # noqa: E402 pylint: disable=wrong-import-position + +import aiohttp # noqa: E402 pylint: disable=wrong-import-position + from .main import run # noqa: E402 pylint: disable=wrong-import-position +oldinit = aiohttp.ClientSession.__init__ # type: ignore + + +def newinit(self, *args, **kwargs): + oldinit(self, *args, **kwargs) + self._source_traceback = traceback.extract_stack(sys._getframe(1)) + + +aiohttp.ClientSession.__init__ = newinit # type: ignore + + run() From ae999da44c7682e2bae428d20de56ad756b9d15a Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 24 Aug 2023 18:02:16 -0400 Subject: [PATCH 141/180] [batch] Fix default query to match v2 (#13493) --- batch/batch/front_end/front_end.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index 4badd5dea48..7bae14fc1bf 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -1717,7 +1717,7 @@ async def ui_delete_batch(request: web.Request, _, batch_id: int) -> NoReturn: async def ui_batches(request: web.Request, userdata: UserData) -> web.Response: session = await aiohttp_session.get_session(request) user = userdata['username'] - q = request.query.get('q', f'user:{user}') + q = request.query.get('q', f'user = {user}' if CURRENT_QUERY_VERSION == 2 else f'user:{user}') last_batch_id = cast_query_param_to_int(request.query.get('last_batch_id')) try: result = await _handle_ui_error(session, _query_batches, request, user, q, CURRENT_QUERY_VERSION, last_batch_id) From ae5c960c4c7b076983104d8bf78e8568800b04b8 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Thu, 24 Aug 2023 19:21:00 -0400 Subject: [PATCH 142/180] [dev-docs] Add document detailing git practices (#13492) I feel like most of us do most of this but we don't have anything to point new developers to. I'm also kind of curious if this is what other folks' understanding of a best practice. Maybe something we can ~~bikeshed~~ bring up in meeting? I also reorganized a bit while I was in the `dev-docs` directory. --- ...ment_process.md => development-process.md} | 5 +- ...{dismiss_review.png => dismiss-review.png} | Bin dev-docs/git-practices.md | 126 ++++++++++++++++++ .../{ => hail-query}/hail-query-lifecycle.md | 0 .../batch/design.rst} | 2 +- .../batch/job-container-design.md} | 0 .../batch/operation.md} | 0 .../creating-a-developer-account.md | 0 dev-docs/{ => services}/key-rotation.md | 0 .../{ => services}/kubernetes-operations.md | 0 dev-docs/{ => services}/letsencrypt.md | 0 .../services-development-faq.md | 0 dev-docs/{ => services}/tls-cookbook.md | 0 dev-docs/{ => services}/tls.md | 0 14 files changed, 130 insertions(+), 3 deletions(-) rename dev-docs/{development_process.md => development-process.md} (99%) rename dev-docs/{dismiss_review.png => dismiss-review.png} (100%) create mode 100644 dev-docs/git-practices.md rename dev-docs/{ => hail-query}/hail-query-lifecycle.md (100%) rename dev-docs/{batch-design.rst => services/batch/design.rst} (99%) rename dev-docs/{batch-container-design.md => services/batch/job-container-design.md} (100%) rename dev-docs/{batch-operation.md => services/batch/operation.md} (100%) rename dev-docs/{ => services}/creating-a-developer-account.md (100%) rename dev-docs/{ => services}/key-rotation.md (100%) rename dev-docs/{ => services}/kubernetes-operations.md (100%) rename dev-docs/{ => services}/letsencrypt.md (100%) rename dev-docs/{ => services}/services-development-faq.md (100%) rename dev-docs/{ => services}/tls-cookbook.md (100%) rename dev-docs/{ => services}/tls.md (100%) diff --git a/dev-docs/development_process.md b/dev-docs/development-process.md similarity index 99% rename from dev-docs/development_process.md rename to dev-docs/development-process.md index c6eee75ebd4..af80d8b4681 100644 --- a/dev-docs/development_process.md +++ b/dev-docs/development-process.md @@ -216,7 +216,8 @@ deploy and then delete existing workers in your namespace. ## PR Once you have a branch that you are happy with, then you create a Pull Request -on the GitHub UI. +on the GitHub UI. For an overview of our practices around git and pull requests, +see [this doc](git-practices.md) You’ll want to add an appropriate reviewer in the "Reviewers" box on the right hand side of the page. If you are an outside contributor and cannot @@ -292,7 +293,7 @@ If your review is requested on a PR submitted by an outside contributor, you sho responsible for ensuring that the PR does not go stale and is eventually merged or closed. -![](dismiss_review.png) +![](dismiss-review.png) ## Merge / Deploy diff --git a/dev-docs/dismiss_review.png b/dev-docs/dismiss-review.png similarity index 100% rename from dev-docs/dismiss_review.png rename to dev-docs/dismiss-review.png diff --git a/dev-docs/git-practices.md b/dev-docs/git-practices.md new file mode 100644 index 00000000000..7ec9ec657b2 --- /dev/null +++ b/dev-docs/git-practices.md @@ -0,0 +1,126 @@ +# Forks and PR workflows + +Changes to the Hail codebase are made through pull requests directly to the +`main` branch of the `hail-is/hail` repository. Here are the steps to +take when contributing for the first time and when making a pull request. + + +## First time actions + +In order to keep the `hail-is/hail` repo clean, we ask that contributors develop +features in branches on a personal fork. The first step then is to [fork +the repository](https://github.com/hail-is/hail/fork). + +Once you've done so, clone the repository from your fork. This will set up a +local copy of your fork with a single remote called `origin`. In this document, +we will refer to `origin` as your developer fork, and `upstream` as `hail-is/hail`. +You can check which origins you have configured by running `git remote -v`. + +While feature branches will live on your fork, those branches are still going to want +to be based on the latest changes in `hail-is/hail:main`. So we will add the +upstream repository as another remote so we can pull in those changes. + +```bash +git remote add upstream https://github.com/hail-is/hail.git +``` + +If you run `git remote -v` again, you should see something like the following: + +``` +origin https://github.com//hail.git (fetch) +origin https://github.com//hail.git (push) +upstream https://github.com/hail-is/hail.git (fetch) +upstream https://github.com/hail-is/hail.git (push) +``` + +When starting a new feature branch, retrieve the latest changes from +upstream and checkout a branch based on those changes: + +```bash +git fetch upstream +git checkout -b upstream/main +``` + +## While developing a feature + +`hail-is/hail:main` moves quickly, and it is likely that it will have progressed +significantly while you work on a feature. This is not in itself a problem, +but can cause headaches if changes in upstream `main` conflict with the code you +are working on. To cope with this, we recommend [rebasing](https://git-scm.com/docs/git-rebase#_description) +regularly and often. Rebasing will incoporate the new changes from main into your +branch and allow you to resolve any conflicts that might have developed along the +way. + +To rebase your feature branch on the latest upstream main, run + +```bash +git fetch upstream +git rebase upstream/main +``` + +The `-i` here is optional but extremely informative, and can help you understand +what the rebase is doing. You can leave all your commits as `pick`, and keep +all your commits while perfoming the rebase, or you can change some commits to +`squash` to collapse your changes into a smaller number of commits. When opening +your change for review, it can be helpful for the reviewers if you squash your +branch into a small number of self-contained commits. For example, if your change +requires upgrading a dependency, it is helpful to put the dependency upgrades +into a separate commmit from the code changes. + + +## Making a PR + +When a feature branch is ready for PR, push the branch to your fork: + +```bash +git push origin +``` + +If you have already done this before but have since rebased, you may get +an error because the history on your fork is no longer a prefix of your local +branch's history. Force push your branch to overwrite the history on GitHub +with that of your local branch. + +```bash +git push --force-with-lease origin +``` + +You can then make a PR on GitHub from the branch on your fork to `hail-is/hail:main`. + + +## While a feature is in PR + +If a reviewer requests changes on a PR, you can make those changes on +your feature branch and `git push origin ` to reflect those +changes in your PR. + +However, once the review process has begun it is best not to `rebase` the branch +any further. Doing so rewrites the commit history of the PR and causes GitHub to lose +when and where review comments were made. It also removes the PR reviewer's ability +to use the GitHub feature "see changes since last review", which can be very +helpful for long PRs and review processes. + +If an existing PR runs into merge conflicts, you can instead merge main *into* your +feature branch. + +```bash +git fetch upstream +git checkout +git merge upstream/main + +... resolve any conflicts and `git add` any resolved files ... + +git commit +git push origin +``` + +Instead of rewriting the history and losing the state of the review, this will +add a single merge commit that can be ignored by the reviewer. + +Another reason not to force push once a change is in PR is if another collaborator +adds changes to the branch. If someone else has made a change to your PR, pull +those changes into your local branch before adding new changes by running + +```bash +git pull origin +``` diff --git a/dev-docs/hail-query-lifecycle.md b/dev-docs/hail-query/hail-query-lifecycle.md similarity index 100% rename from dev-docs/hail-query-lifecycle.md rename to dev-docs/hail-query/hail-query-lifecycle.md diff --git a/dev-docs/batch-design.rst b/dev-docs/services/batch/design.rst similarity index 99% rename from dev-docs/batch-design.rst rename to dev-docs/services/batch/design.rst index 0b0ea2005e6..644a735b130 100644 --- a/dev-docs/batch-design.rst +++ b/dev-docs/services/batch/design.rst @@ -30,7 +30,7 @@ system is ~16 million jobs. Likewise, QoB consists of a single, nonpreemptible driver job and subsequent sets of updates of jobs to the directed acyclic graph (DAG) for subsequent stages of worker jobs. There is a single job per partition within a stage. The number -of jobs within a stage can be on the order of 100K jobs. +of jobs within a stage can be on the order of 100K jobs. **************************** diff --git a/dev-docs/batch-container-design.md b/dev-docs/services/batch/job-container-design.md similarity index 100% rename from dev-docs/batch-container-design.md rename to dev-docs/services/batch/job-container-design.md diff --git a/dev-docs/batch-operation.md b/dev-docs/services/batch/operation.md similarity index 100% rename from dev-docs/batch-operation.md rename to dev-docs/services/batch/operation.md diff --git a/dev-docs/creating-a-developer-account.md b/dev-docs/services/creating-a-developer-account.md similarity index 100% rename from dev-docs/creating-a-developer-account.md rename to dev-docs/services/creating-a-developer-account.md diff --git a/dev-docs/key-rotation.md b/dev-docs/services/key-rotation.md similarity index 100% rename from dev-docs/key-rotation.md rename to dev-docs/services/key-rotation.md diff --git a/dev-docs/kubernetes-operations.md b/dev-docs/services/kubernetes-operations.md similarity index 100% rename from dev-docs/kubernetes-operations.md rename to dev-docs/services/kubernetes-operations.md diff --git a/dev-docs/letsencrypt.md b/dev-docs/services/letsencrypt.md similarity index 100% rename from dev-docs/letsencrypt.md rename to dev-docs/services/letsencrypt.md diff --git a/dev-docs/services-development-faq.md b/dev-docs/services/services-development-faq.md similarity index 100% rename from dev-docs/services-development-faq.md rename to dev-docs/services/services-development-faq.md diff --git a/dev-docs/tls-cookbook.md b/dev-docs/services/tls-cookbook.md similarity index 100% rename from dev-docs/tls-cookbook.md rename to dev-docs/services/tls-cookbook.md diff --git a/dev-docs/tls.md b/dev-docs/services/tls.md similarity index 100% rename from dev-docs/tls.md rename to dev-docs/services/tls.md From 1b46201069fa11548c98e0dfd7111651745c4be4 Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 24 Aug 2023 20:38:11 -0400 Subject: [PATCH 143/180] [github] apply needs-triage label to each bug report (#13417) I also suggested gist.github.com for large logs. This will allow us to quickly see new issues from users. We might want other forms / to generalize this form if we want support requests to go to GitHub too. cc: @jigold --- .github/ISSUE_TEMPLATE/bug-report.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 51c8de1f73b..80fa445ae15 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,5 +1,6 @@ name: Bug Report description: Report a bug +labels: needs-triage body: - type: textarea id: what-happened @@ -19,5 +20,5 @@ body: id: log attributes: label: Relevant log output - description: Please copy and paste any relevant log output. + description: Please copy and paste any relevant log output. If too large, please put in https://gist.github.com and provide the link. render: shell From 9cb49a0add796472c6261e63c6a8802a93c0175d Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 24 Aug 2023 21:52:23 -0400 Subject: [PATCH 144/180] [fs] remove Azure _debug parameters (#13472) This was added in https://github.com/hail-is/hail/pull/12421 to help debug errors in `testSeekMoreThanMaxInt`. We have not seen that transient error in a while and I think the switch to https://github.com/hail-is/hail/pull/12590 might have fixed some underlying misuse of `AppendBlobClient` (by not using it). --- .../main/scala/is/hail/io/bgen/StagedBGENReader.scala | 2 +- hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala | 10 +--------- hail/src/main/scala/is/hail/io/fs/FS.scala | 7 +++---- .../src/main/scala/is/hail/io/fs/GoogleStorageFS.scala | 3 +-- hail/src/main/scala/is/hail/io/fs/HadoopFS.scala | 3 +-- hail/src/main/scala/is/hail/io/fs/RouterFS.scala | 2 +- hail/src/test/scala/is/hail/fs/FSSuite.scala | 4 +--- 7 files changed, 9 insertions(+), 22 deletions(-) diff --git a/hail/src/main/scala/is/hail/io/bgen/StagedBGENReader.scala b/hail/src/main/scala/is/hail/io/bgen/StagedBGENReader.scala index 9dd84248082..9a40db3c7aa 100644 --- a/hail/src/main/scala/is/hail/io/bgen/StagedBGENReader.scala +++ b/hail/src/main/scala/is/hail/io/bgen/StagedBGENReader.scala @@ -481,7 +481,7 @@ object BGENFunctions extends RegistryFunctions { val bufferSize = _bufferSize.asInt.value val cbfis = cb.memoize(Code.newInstance[HadoopFSDataBinaryReader, SeekableDataInputStream]( - mb.getFS.invoke[String, Boolean, SeekableDataInputStream]("openNoCompression", path, false))) + mb.getFS.invoke[String, SeekableDataInputStream]("openNoCompression", path))) val header = cb.memoize(Code.invokeScalaObject3[HadoopFSDataBinaryReader, String, Long, BgenHeader]( LoadBgen.getClass, "readState", cbfis, path, mb.getFS.invoke[String, Long]("getFileSize", path))) diff --git a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala index 60f3d587a24..066f41a6063 100644 --- a/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/AzureStorageFS.scala @@ -262,7 +262,7 @@ class AzureStorageFS(val credentialsJSON: Option[String] = None) extends FS { serviceClientCache.getServiceClient(url).getBlobContainerClient(url.container) } - def openNoCompression(filename: String, _debug: Boolean): SeekableDataInputStream = handlePublicAccessError(filename) { + def openNoCompression(filename: String): SeekableDataInputStream = handlePublicAccessError(filename) { val url = AzureStorageFS.parseUrl(filename) val blobClient: BlobClient = getBlobClient(url) val blobSize = blobClient.getProperties.getBlobSize @@ -296,16 +296,8 @@ class AzureStorageFS(val credentialsJSON: Option[String] = None) extends FS { bb.flip() assert(bb.position() == 0 && bb.remaining() > 0) - if (_debug) { - val byteContents = bb.array().map("%02X" format _).mkString - log.info(s"AzureStorageFS.openNoCompression SeekableInputStream: pos=$pos blobSize=$blobSize count=$count response.getStatusCode()=${response.getStatusCode()} bb.toString()=${bb} byteContents=${byteContents}") - } - bb.remaining() } else { - if (_debug) { - log.info(s"AzureStorageFS.openNoCompression SeekableInputStream: pos=$pos blobSize=$blobSize count=$count response.getStatusCode()=${response.getStatusCode()}") - } -1 } } diff --git a/hail/src/main/scala/is/hail/io/fs/FS.scala b/hail/src/main/scala/is/hail/io/fs/FS.scala index 170918105a9..dd5b6c63e1b 100644 --- a/hail/src/main/scala/is/hail/io/fs/FS.scala +++ b/hail/src/main/scala/is/hail/io/fs/FS.scala @@ -328,8 +328,7 @@ trait FS extends Serializable { "" } - final def openNoCompression(filename: String): SeekableDataInputStream = openNoCompression(filename, false) - def openNoCompression(filename: String, _debug: Boolean): SeekableDataInputStream + def openNoCompression(filename: String): SeekableDataInputStream def readNoCompression(filename: String): Array[Byte] = retryTransientErrors { using(openNoCompression(filename)) { is => @@ -411,8 +410,8 @@ trait FS extends Serializable { new Thread(() => delete(filename, recursive = false))) } - def open(path: String, codec: CompressionCodec, _debug: Boolean = false): InputStream = { - val is = openNoCompression(path, _debug) + def open(path: String, codec: CompressionCodec): InputStream = { + val is = openNoCompression(path) if (codec != null) codec.makeInputStream(is) else diff --git a/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala b/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala index 6ad7ae5fc7d..62ef5d3506c 100644 --- a/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala @@ -213,8 +213,7 @@ class GoogleStorageFS( } } - def openNoCompression(filename: String, _debug: Boolean = false): SeekableDataInputStream = retryTransientErrors { - assert(!_debug) + def openNoCompression(filename: String): SeekableDataInputStream = retryTransientErrors { val url = parseUrl(filename) val is: SeekableInputStream = new FSSeekableInputStream { diff --git a/hail/src/main/scala/is/hail/io/fs/HadoopFS.scala b/hail/src/main/scala/is/hail/io/fs/HadoopFS.scala index 7a74c696196..bc010f887c3 100644 --- a/hail/src/main/scala/is/hail/io/fs/HadoopFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/HadoopFS.scala @@ -100,8 +100,7 @@ class HadoopFS(private[this] var conf: SerializableHadoopConfiguration) extends HadoopFS.toPositionedOutputStream(os)) } - def openNoCompression(filename: String, _debug: Boolean = false): SeekableDataInputStream = { - assert(!_debug) + def openNoCompression(filename: String): SeekableDataInputStream = { val fs = getFileSystem(filename) val hPath = new hadoop.fs.Path(filename) val is = try { diff --git a/hail/src/main/scala/is/hail/io/fs/RouterFS.scala b/hail/src/main/scala/is/hail/io/fs/RouterFS.scala index aff5b27ed4b..363384555bc 100644 --- a/hail/src/main/scala/is/hail/io/fs/RouterFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/RouterFS.scala @@ -19,7 +19,7 @@ class RouterFS(fss: IndexedSeq[FS]) extends FS { override def createCachedNoCompression(filename: String): PositionedDataOutputStream = lookupFS(filename).createCachedNoCompression(filename) - def openNoCompression(filename: String, _debug: Boolean = false): SeekableDataInputStream = lookupFS(filename).openNoCompression(filename, _debug) + def openNoCompression(filename: String): SeekableDataInputStream = lookupFS(filename).openNoCompression(filename) def createNoCompression(filename: String): PositionedDataOutputStream = lookupFS(filename).createNoCompression(filename) diff --git a/hail/src/test/scala/is/hail/fs/FSSuite.scala b/hail/src/test/scala/is/hail/fs/FSSuite.scala index b27d62581fd..2ae121704ec 100644 --- a/hail/src/test/scala/is/hail/fs/FSSuite.scala +++ b/hail/src/test/scala/is/hail/fs/FSSuite.scala @@ -354,9 +354,7 @@ trait FSSuite extends TestNGSuite { assert(fs.exists(f)) - val debug = this.isInstanceOf[AzureStorageFSSuite] - - using(fs.open(f, fs.getCodecFromPath(f), _debug=debug)) { is => + using(fs.open(f, fs.getCodecFromPath(f))) { is => is match { case base: Seekable => base.seek(Int.MaxValue + 2.toLong) case base: org.apache.hadoop.fs.Seekable => base.seek(Int.MaxValue + 2.toLong) From ab316ce6e94048d4be16818c7b3a98c0be852764 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 25 Aug 2023 08:06:44 -0400 Subject: [PATCH 145/180] [query] clarify file format version vs library version (#13494) Addresses user confusion in https://discuss.hail.is/t/potential-outdated-error-statement-for-hail-version-incompatibility/3562. --- hail/python/hail/docs/change_log.md | 70 ++++++++++++++++--- .../expr/ir/AbstractMatrixTableSpec.scala | 4 +- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/hail/python/hail/docs/change_log.md b/hail/python/hail/docs/change_log.md index 2f1ff73336e..346fcc7d0ad 100644 --- a/hail/python/hail/docs/change_log.md +++ b/hail/python/hail/docs/change_log.md @@ -21,17 +21,36 @@ Hail as particularly buggy (especially compared to one-off untested scripts pervasive in bioinformatics!), Hail 0.2 is a partial realization of a larger vision. +### What is the difference between the Hail Python library version and the native file format version? + +The Hail Python library version, the version you see on [PyPI](https://pypi.org/project/hail/), in +`pip`, or in `hl.version()` changes every time we release the Python library. The Hail native file +format version only changes when we change the format of Hail Table and MatrixTable files. If a +version of the Python library introduces a new native file format version, we note that in the +change log. All subsequent versions of the Python library can read the new file format version. + +The native file format changes much slower than the Python library version. It is not currently +possible to view the file format version of a Hail Table or MatrixTable. + ### What stability is guaranteed? -We do not intentionally break back-compatibility of interfaces or file -formats. This means that a script developed to run on Hail 0.2.5 should -continue to work in every subsequent release within the 0.2 major version. -**The exception to this rule is experimental functionality, denoted as -such in the reference documentation, which may change at any time**. +The Hail file formats and Python API are backwards compatible. This means that a script developed to +run on Hail 0.2.5 should continue to work in every subsequent release within the 0.2 major version. +This also means any file written by python library versions 0.2.1 through 0.2.5 can be read by +0.2.5. -Please note that **forward compatibility should not be expected, especially -relating to file formats**: this means that it may not be possible to use -an earlier version of Hail to read files written in a later version. +Forward compatibility of file formats and the Python API is not guaranteed. In particular, a new +file format version is only readable by library versions released after the file format. For +example, Python library version 0.2.119 introduces a new file format version: 1.7.0. All library +versions before 0.2.119, for example 0.2.118, *cannot* read file format version 1.7.0. All library +versions after and including 0.2.119 *can* read file format version 1.7.0. + +Each version of the Hail Python library can only write files using the latest file format version it +supports. + +**The hl.experimental package and other methods marked experimental in the docs are exempt from this +policy. Their functionality or even existence may change without notice. Please contact us if you +critically depend on experimental functionality.** ## Version 0.2.120 @@ -79,8 +98,9 @@ Released 2023-06-28 - (hail#13173) Fix globbing in scala blob storage filesystem implementations. ### File Format -- The native file format version is now 1.7.0. Older versions of hail will not - be able to read tables or matrix tables written by this version of hail. + +- The native file format version is now 1.7.0. Older versions of Hail will not + be able to read tables or matrix tables written by this version of Hail. ## Version 0.2.118 @@ -739,6 +759,11 @@ Release 2022-01-24 - (hail#11219) We no longer officially support Python 3.6, though it may continue to work in the short term. - (hail#11220) We support building hail with Java 11. +### File Format + +- The native file format version is now 1.6.0. Older versions of Hail will not + be able to read tables or matrix tables written by this version of Hail. + --- ## Version 0.2.81 @@ -1172,6 +1197,11 @@ Released 2020-08-19 dataproc` now features the same Spark monitoring widget found in the "Hail" kernel. There is now no reason to use the "Hail" kernel. +### File Format + +- The native file format version is now 1.5.0. Older versions of Hail will not + be able to read tables or matrix tables written by this version of Hail. + --- ## Version 0.2.54 @@ -1532,6 +1562,11 @@ Released 2020-03-12 - (hail#8253) `hailctl dataproc` now supports new flags `--requester-pays-allow-all` and `--requester-pays-allow-buckets`. This will configure your hail installation to be able to read from requester pays buckets. The charges for reading from these buckets will be billed to the project that the cluster is created in. - (hail#8268) The data sources for VEP have been moved to `gs://hail-us-vep`, `gs://hail-eu-vep`, and `gs://hail-uk-vep`, which are requester-pays buckets in Google Cloud. `hailctl dataproc` will automatically infer which of these buckets you should pull data from based on the region your cluster is spun up in. If you are in none of those regions, please contact us on discuss.hail.is. +### File Format + +- The native file format version is now 1.4.0. Older versions of Hail will not + be able to read tables or matrix tables written by this version of Hail. + --- @@ -1726,6 +1761,11 @@ Released 2019-10-24 ### Performance Improvements - (hail#7355) Improve performance of IR copying. +### File Format + +- The native file format version is now 1.3.0. Older versions of Hail will not + be able to read tables or matrix tables written by this version of Hail. + ## Version 0.2.25 Released 2019-10-14 @@ -1746,6 +1786,11 @@ Released 2019-10-14 - (hail#7195)(hail#7194) Improve performance of `group[_rows]_by` / `aggregate`. - (hail#7201) Permit code generation of larger aggregation pipelines. +### File Format + +- The native file format version is now 1.2.0. Older versions of Hail will not + be able to read tables or matrix tables written by this version of Hail. + --- ## Version 0.2.24 @@ -1960,6 +2005,11 @@ Released 2019-07-10 - (hail#6488) Exposed `table.multi_way_zip_join`. This takes a list of tables of identical types, and zips them together into one table. +### File Format + +- The native file format version is now 1.1.0. Older versions of Hail will not + be able to read tables or matrix tables written by this version of Hail. + ----- ## Version 0.2.16 diff --git a/hail/src/main/scala/is/hail/expr/ir/AbstractMatrixTableSpec.scala b/hail/src/main/scala/is/hail/expr/ir/AbstractMatrixTableSpec.scala index 0b23745d117..f7de60c9c09 100644 --- a/hail/src/main/scala/is/hail/expr/ir/AbstractMatrixTableSpec.scala +++ b/hail/src/main/scala/is/hail/expr/ir/AbstractMatrixTableSpec.scala @@ -48,10 +48,10 @@ object RelationalSpec { } if (!FileFormat.version.supports(fileVersion)) - fatal(s"incompatible file format when reading: $path\n supported version: ${ FileFormat.version }, found $fileVersion" + + fatal(s"incompatible file format when reading: $path\n supported file format version: ${ FileFormat.version }, found file format version $fileVersion" + s"\n The cause of this error is usually an attempt to use an older version of Hail to read files " + s"generated by a newer version. This is not supported (Hail native files are back-compatible, but not forward-compatible)." + - s"\n To read this file, use a newer version of Hail.") + s"\n To read this file, use a newer version of Hail. Note that the file format version and the Hail Python library version are not the same.") jv } From b6e749ee4fafc05d6847f7d0e3b414f6850bdc01 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 25 Aug 2023 11:16:50 -0400 Subject: [PATCH 146/180] [batch] remove use of smart quotes in docs (#13496) I presume this was meant to be normal double quotes. --- hail/python/hailtop/batch/docs/advanced_search_help.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hail/python/hailtop/batch/docs/advanced_search_help.rst b/hail/python/hailtop/batch/docs/advanced_search_help.rst index 83f2594c3fe..e722db01d7f 100644 --- a/hail/python/hailtop/batch/docs/advanced_search_help.rst +++ b/hail/python/hailtop/batch/docs/advanced_search_help.rst @@ -14,7 +14,7 @@ Exact Match Expression A single word enclosed with double quotes that is an exact match for either the name or value of an attribute. -**Example:** ``“pca_pipeline”`` +**Example:** ``"pca_pipeline"`` Partial Match Expression ------------------------ From 98bbea02730e3101133b3049f66c6e22037e0f85 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 25 Aug 2023 12:33:21 -0400 Subject: [PATCH 147/180] [batch] use headings instead of captions (#13499) Captions render haphazardly, at least on my browser. Screenshot 2023-08-25 at 10 14 59 --- .../hailtop/batch/docs/advanced_search_help.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/hail/python/hailtop/batch/docs/advanced_search_help.rst b/hail/python/hailtop/batch/docs/advanced_search_help.rst index e722db01d7f..6eec2c39a84 100644 --- a/hail/python/hailtop/batch/docs/advanced_search_help.rst +++ b/hail/python/hailtop/batch/docs/advanced_search_help.rst @@ -43,7 +43,10 @@ listed in the tables below. Allowed operators are dependent on the type of the v keyword, but can be one of ``=``, ``==``, ``!=``, ``>``, ``>=``, ``<``, ``<=``, ``=~``, ``!~``. The right hand side is the value to search against. -.. list-table:: Keywords +Keywords +^^^^^^^^ + +.. list-table:: :widths: 25 25 50 50 :header-rows: 1 @@ -75,8 +78,10 @@ The right hand side is the value to search against. **Example:** ``start_time >= 2023-02-24T17:15:25Z`` +Keywords specific to searching for batches +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. list-table:: Keywords specific to searching for batches +.. list-table:: :widths: 25 25 50 50 :header-rows: 1 @@ -108,9 +113,10 @@ The right hand side is the value to search against. **Example:** ``billing_project = johndoe-trial`` +Keywords specific to searching for jobs in a batch +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. list-table:: Keywords specific to searching for jobs in a batch +.. list-table:: :widths: 25 25 50 50 :header-rows: 1 From 94996333dc72c3ed4e3e6f4088d8d4acddfddcfb Mon Sep 17 00:00:00 2001 From: jigold Date: Fri, 25 Aug 2023 14:57:03 -0400 Subject: [PATCH 148/180] [batch] Search area fixes (#13501) --- batch/batch/front_end/templates/table_search.html | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/batch/batch/front_end/templates/table_search.html b/batch/batch/front_end/templates/table_search.html index 2b3f0e9425b..6116c73336b 100644 --- a/batch/batch/front_end/templates/table_search.html +++ b/batch/batch/front_end/templates/table_search.html @@ -45,8 +45,8 @@ }
-
-
+
+
@@ -64,4 +64,13 @@
+ {% endmacro %} From b63041dfd50010d06998de8586d79e3221794adf Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 25 Aug 2023 16:21:28 -0400 Subject: [PATCH 149/180] [query] improve type hinting for tables (#13468) Without these changes, my IDE cannot deduce that the return value of, say, `select` is a `Table` which prevents jump-to-definition on subsequent method calls. I also received an error about `Table.collect` returning an `ArrayExpression` which it will only do when `_localize=False`. `overload` teaches this fact to the type system. I didn't use the specific expression in `base_expression.py` because that would require an import circularity. --- hail/python/hail/__init__.py | 13 +++++---- hail/python/hail/experimental/function.py | 28 +++++++++++++------ .../hail/expr/expressions/base_expression.py | 8 +++++- hail/python/hail/ir/ir.py | 16 +++++++---- hail/python/hail/table.py | 8 +++++- hail/python/hail/typecheck/check.py | 11 +++++--- hail/python/hailtop/hail_decorator.py | 16 +++++++++++ hail/python/test/hail/helpers.py | 10 +++++-- 8 files changed, 82 insertions(+), 28 deletions(-) create mode 100644 hail/python/hailtop/hail_decorator.py diff --git a/hail/python/hail/__init__.py b/hail/python/hail/__init__.py index 7f0d61f156b..c82b6383cff 100644 --- a/hail/python/hail/__init__.py +++ b/hail/python/hail/__init__.py @@ -30,9 +30,13 @@ # F403 'from .expr import *' used; unable to detect undefined names # F401 '.expr.*' imported but unused # E402 module level import not at top of file +from .expr import * # noqa: E402, F403 +from .expr import aggregators # noqa: E402 +from hail.utils import (Struct, Interval, hadoop_copy, hadoop_open, hadoop_ls, # noqa: E402 + hadoop_stat, hadoop_exists, hadoop_is_file, + hadoop_is_dir, hadoop_scheme_supported, copy_log, ANY_REGION) from .table import Table, GroupedTable, asc, desc # noqa: E402 from .matrixtable import MatrixTable, GroupedMatrixTable # noqa: E402 -from .expr import * # noqa: F403, E402 from .genetics import * # noqa: F403, E402 from .methods import * # noqa: F403, E402 from . import expr # noqa: E402 @@ -47,10 +51,6 @@ from . import backend # noqa: E402 from . import nd # noqa: E402 from . import vds # noqa: E402 -from hail.expr import aggregators as agg # noqa: E402 -from hail.utils import (Struct, Interval, hadoop_copy, hadoop_open, hadoop_ls, # noqa: E402 - hadoop_stat, hadoop_exists, hadoop_is_file, - hadoop_is_dir, hadoop_scheme_supported, copy_log, ANY_REGION) from .context import (init, init_local, init_batch, stop, spark_context, tmp_dir, # noqa: E402 default_reference, get_reference, set_global_seed, reset_global_randomness, @@ -58,7 +58,8 @@ current_backend, debug_info, citation, cite_hail, cite_hail_bibtex, version, TemporaryFilename, TemporaryDirectory) -scan = agg.aggregators.ScanFunctions({name: getattr(agg, name) for name in agg.__all__}) +agg = aggregators +scan = aggregators.aggregators.ScanFunctions({name: getattr(agg, name) for name in agg.__all__}) __all__ = [ 'init', diff --git a/hail/python/hail/experimental/function.py b/hail/python/hail/experimental/function.py index 3e08d4dbda8..28fff373d9c 100644 --- a/hail/python/hail/experimental/function.py +++ b/hail/python/hail/experimental/function.py @@ -1,25 +1,35 @@ -from typing import Optional -from hail.expr.expressions import construct_expr, expr_any, unify_all -from hail.expr.types import hail_type +from typing import Optional, Tuple, Sequence, Callable +from hail.expr.expressions import construct_expr, expr_any, unify_all, Expression +from hail.expr.types import hail_type, HailType from hail.ir import Apply, Ref from hail.typecheck import typecheck, nullable, tupleof, anytype from hail.utils.java import Env -class Function(object): - def __init__(self, f, param_types, ret_type, name, type_args=()): +class Function(): + def __init__(self, + f: Callable[..., Expression], + param_types: Sequence[HailType], + ret_type: HailType, + name: str, + type_args: Tuple[HailType, ...] = () + ): self._f = f self._name = name self._type_args = type_args self._param_types = param_types self._ret_type = ret_type - def __call__(self, *args): + def __call__(self, *args: Expression) -> Expression: return self._f(*args) @typecheck(f=anytype, param_types=hail_type, _name=nullable(str), type_args=tupleof(hail_type)) -def define_function(f, *param_types, _name: Optional[str] = None, type_args=()) -> Function: +def define_function(f: Callable[..., Expression], + *param_types: HailType, + _name: Optional[str] = None, + type_args: Tuple[HailType, ...] = () + ) -> Function: mname = _name if _name is not None else Env.get_uid() param_names = [Env.get_uid(mname) for _ in param_types] body = f(*(construct_expr(Ref(pn), pt) for pn, pt in zip(param_names, param_types))) @@ -28,8 +38,8 @@ def define_function(f, *param_types, _name: Optional[str] = None, type_args=()) Env.backend().register_ir_function(mname, type_args, param_names, param_types, ret_type, body) @typecheck(args=expr_any) - def f(*args): + def fun(*args: Expression) -> Expression: indices, aggregations = unify_all(*args) return construct_expr(Apply(mname, ret_type, *(a._ir for a in args), type_args=type_args), ret_type, indices, aggregations) - return Function(f, param_types, ret_type, mname, type_args) + return Function(fun, param_types, ret_type, mname, type_args) diff --git a/hail/python/hail/expr/expressions/base_expression.py b/hail/python/hail/expr/expressions/base_expression.py index f9e203bc56a..b9f1a6e83dc 100644 --- a/hail/python/hail/expr/expressions/base_expression.py +++ b/hail/python/hail/expr/expressions/base_expression.py @@ -1,4 +1,4 @@ -from typing import Tuple, Mapping +from typing import Tuple, Mapping, overload, Any, List import numpy as np import pandas as pd @@ -1101,6 +1101,12 @@ def take(self, n, _localize=True): return hl.eval(e) return e + @overload + def collect(self) -> List[Any]: + ... + @overload + def collect(self, _localize=False) -> 'Expression': + ... @typecheck_method(_localize=bool) def collect(self, _localize=True): """Collect all records of an expression into a local list. diff --git a/hail/python/hail/ir/ir.py b/hail/python/hail/ir/ir.py index a013f00c45f..85bc52aff5b 100644 --- a/hail/python/hail/ir/ir.py +++ b/hail/python/hail/ir/ir.py @@ -1,8 +1,10 @@ +from typing import Callable, TypeVar, cast +from typing_extensions import ParamSpec import copy import json from collections import defaultdict -import decorator +from hailtop.hail_decorator import decorator import hail from hail.expr.types import dtype, HailType, hail_type, tint32, tint64, \ @@ -2972,19 +2974,23 @@ def register_seeded_function(name, param_types, ret_type): _register(_seeded_function_registry, name, (param_types, ret_type)) -def udf(*param_types): +T = TypeVar('T') +P = ParamSpec('P') + + +def udf(*param_types: HailType) -> Callable[[Callable[P, T]], Callable[P, T]]: uid = Env.get_uid() - @decorator.decorator - def wrapper(__original_func, *args, **kwargs): + @decorator + def wrapper(__original_func: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T: registry = hail.ir.ir._udf_registry if uid in registry: f = registry[uid] else: f = hail.experimental.define_function(__original_func, *param_types, _name=uid) registry[uid] = f - return f(*args, **kwargs) + return cast(Callable[P, T], f)(*args, **kwargs) return wrapper diff --git a/hail/python/hail/table.py b/hail/python/hail/table.py index 1d3bd75a004..2865491aeed 100644 --- a/hail/python/hail/table.py +++ b/hail/python/hail/table.py @@ -4,7 +4,7 @@ import numpy as np import pyspark import pprint -from typing import Optional, Dict, Callable, Sequence, Union +from typing import Optional, Dict, Callable, Sequence, Union, List, overload from hail.expr.expressions import Expression, StructExpression, \ BooleanExpression, expr_struct, expr_any, expr_bool, analyze, Indices, \ @@ -2127,6 +2127,12 @@ def unpersist(self) -> 'Table': """ return Env.backend().unpersist(self) + @overload + def collect(self) -> List[hl.Struct]: + ... + @overload + def collect(self, _localize=False) -> hl.ArrayExpression: + ... @typecheck_method(_localize=bool, _timed=bool) def collect(self, _localize=True, *, _timed=False): """Collect the rows of the table into a local list. diff --git a/hail/python/hail/typecheck/check.py b/hail/python/hail/typecheck/check.py index 4673565f031..52d3e03a85a 100644 --- a/hail/python/hail/typecheck/check.py +++ b/hail/python/hail/typecheck/check.py @@ -1,8 +1,9 @@ +from typing import TypeVar, Callable import re import inspect import abc import collections -from decorator import decorator +from hailtop.hail_decorator import decorator class TypecheckFailure(Exception): @@ -566,7 +567,6 @@ def check_all(f, args, kwargs, checks, is_method): kwargs_[kwarg_name] = kwargs_check(arg, name, kwarg_name, checker) return args_, kwargs_ - def typecheck_method(**checkers): return _make_dec(checkers, is_method=True) @@ -575,11 +575,14 @@ def typecheck(**checkers): return _make_dec(checkers, is_method=False) -def _make_dec(checkers, is_method): +T = TypeVar('T') + + +def _make_dec(checkers, is_method: bool) -> Callable[[Callable[..., T]], Callable[..., T]]: checkers = {k: only(v) for k, v in checkers.items()} @decorator - def wrapper(__original_func, *args, **kwargs): + def wrapper(__original_func: Callable[..., T], *args, **kwargs) -> T: args_, kwargs_ = check_all(__original_func, args, kwargs, checkers, is_method=is_method) return __original_func(*args_, **kwargs_) diff --git a/hail/python/hailtop/hail_decorator.py b/hail/python/hailtop/hail_decorator.py new file mode 100644 index 00000000000..979d1f41105 --- /dev/null +++ b/hail/python/hailtop/hail_decorator.py @@ -0,0 +1,16 @@ +from typing import TypeVar, Callable, cast, Protocol +from typing_extensions import ParamSpec +from decorator import decorator as _decorator + +P = ParamSpec('P') +T = TypeVar('T') + +class Wrapper(Protocol[P, T]): + def __call__(self, fun: Callable[P, T], /, *args: P.args, **kwargs: P.kwargs) -> T: + ... + + +def decorator( + fun: Wrapper[P, T] +) -> Callable[[Callable[P, T]], Callable[P, T]]: + return cast(Callable[[Callable[P, T]], Callable[P, T]], _decorator(fun)) diff --git a/hail/python/test/hail/helpers.py b/hail/python/test/hail/helpers.py index ab76c88601e..6d4a8661e06 100644 --- a/hail/python/test/hail/helpers.py +++ b/hail/python/test/hail/helpers.py @@ -1,8 +1,10 @@ +from typing import Callable, TypeVar +from typing_extensions import ParamSpec import os from timeit import default_timer as timer import unittest import pytest -from decorator import decorator +from hailtop.hail_decorator import decorator from hail.utils.java import choose_backend import hail as hl @@ -121,10 +123,14 @@ def create_all_values_datasets(): return (create_all_values_table(), create_all_values_matrix_table()) +P = ParamSpec('P') +T = TypeVar('T') + + def skip_unless_spark_backend(reason='requires Spark'): from hail.backend.spark_backend import SparkBackend @decorator - def wrapper(func, *args, **kwargs): + def wrapper(func, *args, **kwargs) -> T: if isinstance(hl.utils.java.Env.backend(), SparkBackend): return func(*args, **kwargs) else: From e702d25fde805de0c2ae9dc17a38e51706950150 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Fri, 25 Aug 2023 17:43:33 -0400 Subject: [PATCH 150/180] [batch] Favor configuration_of and get_remote_tmpdir over get_user_config (#13503) Just some cleanup, all in test files. --------- Co-authored-by: jigold --- batch/test/conftest.py | 7 +++++++ batch/test/test_batch.py | 11 ++++------- batch/test/test_dag.py | 10 +++------- hail/python/test/hailtop/batch/test_batch.py | 8 +++++--- .../test/hailtop/batch/test_batch_pool_executor.py | 3 +-- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/batch/test/conftest.py b/batch/test/conftest.py index eb5bbc38a43..fc04bda3222 100644 --- a/batch/test/conftest.py +++ b/batch/test/conftest.py @@ -4,6 +4,8 @@ import pytest +from hailtop.config import get_remote_tmpdir + log = logging.getLogger(__name__) @@ -14,6 +16,11 @@ def log_before_after(): log.info('ending test') +@pytest.fixture(scope='module') +def remote_tmpdir(): + return get_remote_tmpdir('batch_tests') + + def pytest_collection_modifyitems(config, items): # pylint: disable=unused-argument n_splits = int(os.environ.get('HAIL_RUN_IMAGE_SPLITS', '1')) split_index = int(os.environ.get('HAIL_RUN_IMAGE_SPLIT_INDEX', '-1')) diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 8e1190c4c1e..0128979fa92 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -12,7 +12,7 @@ from hailtop.batch.backend import HAIL_GENETICS_HAILTOP_IMAGE from hailtop.batch_client import BatchNotCreatedError, JobNotSubmittedError from hailtop.batch_client.client import Batch, BatchClient -from hailtop.config import get_deploy_config, get_user_config +from hailtop.config import get_deploy_config from hailtop.test_utils import skip_in_azure from hailtop.utils import delay_ms_for_try, external_requests_client_session, retry_response_returning_functions from hailtop.utils.rich_progress_bar import BatchProgressBar @@ -1114,9 +1114,8 @@ def test_verify_no_access_to_metadata_server(client: BatchClient): assert "Connection timed out" in job_log['main'], str((job_log, b.debug_info())) -def test_submit_batch_in_job(client: BatchClient): +def test_submit_batch_in_job(client: BatchClient, remote_tmpdir: str): b = create_batch(client) - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') script = f'''import hailtop.batch as hb backend = hb.ServiceBackend("test", remote_tmpdir="{remote_tmpdir}") b = hb.Batch(backend=backend) @@ -1135,11 +1134,10 @@ def test_submit_batch_in_job(client: BatchClient): assert status['state'] == 'Success', str((status, b.debug_info())) -def test_cant_submit_to_default_with_other_ns_creds(client: BatchClient): +def test_cant_submit_to_default_with_other_ns_creds(client: BatchClient, remote_tmpdir: str): DOMAIN = os.environ['HAIL_DOMAIN'] NAMESPACE = os.environ['HAIL_DEFAULT_NAMESPACE'] - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') script = f'''import hailtop.batch as hb backend = hb.ServiceBackend("test", remote_tmpdir="{remote_tmpdir}") b = hb.Batch(backend=backend) @@ -1215,9 +1213,8 @@ def test_cannot_contact_other_internal_ips(client: BatchClient): @skip_in_azure -def test_hadoop_can_use_cloud_credentials(client: BatchClient): +def test_hadoop_can_use_cloud_credentials(client: BatchClient, remote_tmpdir: str): token = os.environ["HAIL_TOKEN"] - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') b = create_batch(client) script = f'''import hail as hl import secrets diff --git a/batch/test/test_dag.py b/batch/test/test_dag.py index 08eb96a217e..9989e5676bd 100644 --- a/batch/test/test_dag.py +++ b/batch/test/test_dag.py @@ -8,7 +8,6 @@ from hailtop.batch_client import aioclient from hailtop.batch_client.client import BatchClient, Job -from hailtop.config import get_user_config from .utils import DOCKER_ROOT_IMAGE, batch_status_job_counter, create_batch, legacy_batch_status @@ -192,8 +191,7 @@ def test_no_parents_allowed_in_other_batches(client): assert False -def test_input_dependency(client): - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') +def test_input_dependency(client, remote_tmpdir): batch = create_batch(client) head = batch.create_job( DOCKER_ROOT_IMAGE, @@ -214,8 +212,7 @@ def test_input_dependency(client): assert tail_log['main'] == 'head1\nhead2\n', str((tail_log, batch.debug_info())) -def test_input_dependency_wildcard(client): - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') +def test_input_dependency_wildcard(client, remote_tmpdir): batch = create_batch(client) head = batch.create_job( DOCKER_ROOT_IMAGE, @@ -236,8 +233,7 @@ def test_input_dependency_wildcard(client): assert tail_log['main'] == 'head1\nhead2\n', str((tail_log, batch.debug_info())) -def test_input_dependency_directory(client): - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') +def test_input_dependency_directory(client, remote_tmpdir): batch = create_batch(client) head = batch.create_job( DOCKER_ROOT_IMAGE, diff --git a/hail/python/test/hailtop/batch/test_batch.py b/hail/python/test/hailtop/batch/test_batch.py index 9f5fc08d166..48b4769b701 100644 --- a/hail/python/test/hailtop/batch/test_batch.py +++ b/hail/python/test/hailtop/batch/test_batch.py @@ -16,12 +16,14 @@ from hailtop.batch.exceptions import BatchException from hailtop.batch.globals import arg_max from hailtop.utils import grouped, async_to_blocking -from hailtop.config import get_user_config +from hailtop.config import get_remote_tmpdir, configuration_of from hailtop.batch.utils import concatenate from hailtop.aiotools.router_fs import RouterAsyncFS from hailtop.test_utils import skip_in_azure from hailtop.httpx import ClientResponseError +from hailtop.config.variables import ConfigVariable + DOCKER_ROOT_IMAGE = os.environ.get('DOCKER_ROOT_IMAGE', 'ubuntu:20.04') PYTHON_DILL_IMAGE = 'hailgenetics/python-dill:3.9-slim' @@ -480,7 +482,7 @@ class ServiceTests(unittest.TestCase): def setUp(self): self.backend = ServiceBackend() - remote_tmpdir = get_user_config().get('batch', 'remote_tmpdir') + remote_tmpdir = get_remote_tmpdir('hailtop_test_batch_service_tests') if not remote_tmpdir.endswith('/'): remote_tmpdir += '/' self.remote_tmpdir = remote_tmpdir + str(uuid.uuid4()) + '/' @@ -1093,7 +1095,7 @@ def qob_in_batch(): j = bb.new_python_job() j.env('HAIL_QUERY_BACKEND', 'batch') - j.env('HAIL_BATCH_BILLING_PROJECT', get_user_config().get('batch', 'billing_project')) + j.env('HAIL_BATCH_BILLING_PROJECT', configuration_of(ConfigVariable.BATCH_BILLING_PROJECT, None, '')) j.env('HAIL_BATCH_REMOTE_TMPDIR', self.remote_tmpdir) j.call(qob_in_batch) diff --git a/hail/python/test/hailtop/batch/test_batch_pool_executor.py b/hail/python/test/hailtop/batch/test_batch_pool_executor.py index b48911d4d06..825f35d88b2 100644 --- a/hail/python/test/hailtop/batch/test_batch_pool_executor.py +++ b/hail/python/test/hailtop/batch/test_batch_pool_executor.py @@ -29,8 +29,7 @@ def backend(): @pytest.fixture(scope='session', autouse=True) def check_for_running_batches(): yield - billing_project = get_user_config().get('batch', 'billing_project', fallback=None) - with BatchClient(billing_project=billing_project) as bc: + with BatchClient('') as bc: for id in submitted_batch_ids: b = bc.get_batch(id) tries = 1 From 06e20aec558c89cd634f1f8845cb555a705479e0 Mon Sep 17 00:00:00 2001 From: jigold Date: Mon, 28 Aug 2023 14:31:41 -0400 Subject: [PATCH 151/180] [batch] Drop unused SQL functions (#13510) I want to cleanup some of the old database functions as they're no longer used (`close_batch`) and not tested / not used in production / hard to maintain (`recompute_incremental`). The `recompute_incremental` was there in the early days of Batch when we needed to recompute the user_inst_coll_resources table etc. for a single migration to improve cancelling. We have not used it since. I double checked `close_batch` isn't used in the Python code, but would appreciate it if you could also check as well. --- batch/sql/cleanup-deprecated-functions.sql | 2 + batch/sql/estimated-current.sql | 140 --------------------- 2 files changed, 2 insertions(+), 140 deletions(-) create mode 100644 batch/sql/cleanup-deprecated-functions.sql diff --git a/batch/sql/cleanup-deprecated-functions.sql b/batch/sql/cleanup-deprecated-functions.sql new file mode 100644 index 00000000000..5896578c6e6 --- /dev/null +++ b/batch/sql/cleanup-deprecated-functions.sql @@ -0,0 +1,2 @@ +DROP PROCEDURE IF EXISTS recompute_incremental; +DROP PROCEDURE IF EXISTS close_batch; diff --git a/batch/sql/estimated-current.sql b/batch/sql/estimated-current.sql index f2fcccf1747..880a999d887 100644 --- a/batch/sql/estimated-current.sql +++ b/batch/sql/estimated-current.sql @@ -984,85 +984,6 @@ BEGIN END IF; END $$ -DROP PROCEDURE IF EXISTS recompute_incremental $$ -CREATE PROCEDURE recompute_incremental( -) BEGIN - - DELETE FROM batches_inst_coll_staging; - DELETE FROM batch_inst_coll_cancellable_resources; - DELETE FROM user_inst_coll_resources; - - DROP TEMPORARY TABLE IF EXISTS `tmp_batch_inst_coll_resources`; - - CREATE TEMPORARY TABLE `tmp_batch_inst_coll_resources` AS ( - SELECT batch_id, batch_state, batch_cancelled, user, job_inst_coll, - COALESCE(SUM(1), 0) as n_jobs, - COALESCE(SUM(job_state = 'Ready' AND cancellable), 0) as n_ready_cancellable_jobs, - COALESCE(SUM(IF(job_state = 'Ready' AND cancellable, cores_mcpu, 0)), 0) as ready_cancellable_cores_mcpu, - COALESCE(SUM(job_state = 'Running' AND cancellable), 0) as n_running_cancellable_jobs, - COALESCE(SUM(IF(job_state = 'Running' AND cancellable, cores_mcpu, 0)), 0) as running_cancellable_cores_mcpu, - COALESCE(SUM(job_state = 'Creating' AND cancellable), 0) as n_creating_cancellable_jobs, - COALESCE(SUM(job_state = 'Running' AND NOT cancelled), 0) as n_running_jobs, - COALESCE(SUM(IF(job_state = 'Running' AND NOT cancelled, cores_mcpu, 0)), 0) as running_cores_mcpu, - COALESCE(SUM(job_state = 'Ready' AND runnable), 0) as n_ready_jobs, - COALESCE(SUM(IF(job_state = 'Ready' AND runnable, cores_mcpu, 0)), 0) as ready_cores_mcpu, - COALESCE(SUM(job_state = 'Creating' AND NOT cancelled), 0) as n_creating_jobs, - COALESCE(SUM(job_state = 'Ready' AND cancelled), 0) as n_cancelled_ready_jobs, - COALESCE(SUM(job_state = 'Running' AND cancelled), 0) as n_cancelled_running_jobs, - COALESCE(SUM(job_state = 'Creating' AND cancelled), 0) as n_cancelled_creating_jobs - FROM ( - SELECT batches.user, - batches.id as batch_id, - batches.state as batch_state, - batches.cancelled as batch_cancelled, - jobs.inst_coll as job_inst_coll, - jobs.state as job_state, - jobs.cores_mcpu, - NOT (jobs.always_run OR jobs.cancelled OR batches.cancelled) AS cancellable, - (jobs.always_run OR NOT (jobs.cancelled OR batches.cancelled)) AS runnable, - (NOT jobs.always_run AND (jobs.cancelled OR batches.cancelled)) AS cancelled - FROM jobs - INNER JOIN batches - ON batches.id = jobs.batch_id - LOCK IN SHARE MODE) as t - GROUP BY batch_id, batch_state, batch_cancelled, user, job_inst_coll - ); - - INSERT INTO batches_inst_coll_staging (batch_id, inst_coll, token, n_jobs, n_ready_jobs, ready_cores_mcpu) - SELECT batch_id, job_inst_coll, 0, n_jobs, n_ready_jobs, ready_cores_mcpu - FROM tmp_batch_inst_coll_resources - WHERE batch_state = 'open'; - - INSERT INTO batch_inst_coll_cancellable_resources (batch_id, inst_coll, token, n_ready_cancellable_jobs, - ready_cancellable_cores_mcpu, n_running_cancellable_jobs, running_cancellable_cores_mcpu, n_creating_cancellable_jobs) - SELECT batch_id, job_inst_coll, 0, n_ready_cancellable_jobs, ready_cancellable_cores_mcpu, - n_running_cancellable_jobs, running_cancellable_cores_mcpu, n_creating_cancellable_jobs - FROM tmp_batch_inst_coll_resources - WHERE NOT batch_cancelled; - - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_ready_jobs, ready_cores_mcpu, - n_running_jobs, running_cores_mcpu, n_creating_jobs, - n_cancelled_ready_jobs, n_cancelled_running_jobs, n_cancelled_creating_jobs) - SELECT t.user, t.job_inst_coll, 0, t.n_ready_jobs, t.ready_cores_mcpu, - t.n_running_jobs, t.running_cores_mcpu, t.n_creating_jobs, - t.n_cancelled_ready_jobs, t.n_cancelled_running_jobs, t.n_cancelled_creating_jobs - FROM (SELECT user, job_inst_coll, - COALESCE(SUM(n_running_jobs), 0) as n_running_jobs, - COALESCE(SUM(running_cores_mcpu), 0) as running_cores_mcpu, - COALESCE(SUM(n_ready_jobs), 0) as n_ready_jobs, - COALESCE(SUM(ready_cores_mcpu), 0) as ready_cores_mcpu, - COALESCE(SUM(n_creating_jobs), 0) as n_creating_jobs, - COALESCE(SUM(n_cancelled_ready_jobs), 0) as n_cancelled_ready_jobs, - COALESCE(SUM(n_cancelled_running_jobs), 0) as n_cancelled_running_jobs, - COALESCE(SUM(n_cancelled_creating_jobs), 0) as n_cancelled_creating_jobs - FROM tmp_batch_inst_coll_resources - WHERE batch_state != 'open' - GROUP by user, job_inst_coll) as t; - - DROP TEMPORARY TABLE IF EXISTS `tmp_batch_inst_coll_resources`; - -END $$ - CREATE PROCEDURE activate_instance( IN in_instance_name VARCHAR(100), IN in_ip_address VARCHAR(100), @@ -1242,67 +1163,6 @@ BEGIN END IF; END $$ -DROP PROCEDURE IF EXISTS close_batch $$ -CREATE PROCEDURE close_batch( - IN in_batch_id BIGINT, - IN in_timestamp BIGINT -) -BEGIN - DECLARE cur_batch_state VARCHAR(40); - DECLARE expected_n_jobs INT; - DECLARE staging_n_jobs INT; - DECLARE staging_n_ready_jobs INT; - DECLARE staging_ready_cores_mcpu BIGINT; - DECLARE cur_user VARCHAR(100); - - START TRANSACTION; - - SELECT `state`, n_jobs INTO cur_batch_state, expected_n_jobs FROM batches - WHERE id = in_batch_id AND NOT deleted - FOR UPDATE; - - IF cur_batch_state != 'open' THEN - COMMIT; - SELECT 0 as rc; - ELSE - SELECT COALESCE(SUM(n_jobs), 0), COALESCE(SUM(n_ready_jobs), 0), COALESCE(SUM(ready_cores_mcpu), 0) - INTO staging_n_jobs, staging_n_ready_jobs, staging_ready_cores_mcpu - FROM batches_inst_coll_staging - WHERE batch_id = in_batch_id - FOR UPDATE; - - SELECT user INTO cur_user FROM batches WHERE id = in_batch_id; - - IF staging_n_jobs = expected_n_jobs THEN - IF expected_n_jobs = 0 THEN - UPDATE batches SET `state` = 'complete', time_completed = in_timestamp, time_closed = in_timestamp - WHERE id = in_batch_id; - ELSE - UPDATE batches SET `state` = 'running', time_closed = in_timestamp - WHERE id = in_batch_id; - END IF; - - INSERT INTO user_inst_coll_resources (user, inst_coll, token, n_ready_jobs, ready_cores_mcpu) - SELECT user, inst_coll, 0, @n_ready_jobs := COALESCE(SUM(n_ready_jobs), 0), @ready_cores_mcpu := COALESCE(SUM(ready_cores_mcpu), 0) - FROM batches_inst_coll_staging - JOIN batches ON batches.id = batches_inst_coll_staging.batch_id - WHERE batch_id = in_batch_id - GROUP BY `user`, inst_coll - ON DUPLICATE KEY UPDATE - n_ready_jobs = n_ready_jobs + @n_ready_jobs, - ready_cores_mcpu = ready_cores_mcpu + @ready_cores_mcpu; - - DELETE FROM batches_inst_coll_staging WHERE batch_id = in_batch_id; - - COMMIT; - SELECT 0 as rc; - ELSE - ROLLBACK; - SELECT 2 as rc, expected_n_jobs, staging_n_jobs as actual_n_jobs, 'wrong number of jobs' as message; - END IF; - END IF; -END $$ - DROP PROCEDURE IF EXISTS cancel_batch $$ CREATE PROCEDURE cancel_batch( IN in_batch_id VARCHAR(100) From a4490b78831c12ba04fb2b9d2291e40c6bacdf64 Mon Sep 17 00:00:00 2001 From: jigold Date: Mon, 28 Aug 2023 15:51:16 -0400 Subject: [PATCH 152/180] [batch] Actually do the cleanup unused functions migration (#13514) Sorry, I forgot to add #13510 to build.yaml. --- build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.yaml b/build.yaml index 1274f633630..037806dc2e0 100644 --- a/build.yaml +++ b/build.yaml @@ -2207,6 +2207,9 @@ steps: - name: turn-on-billing-compaction script: /io/sql/turn_on_billing_compaction.py online: true + - name: cleanup-deprecated-functions + script: /io/sql/cleanup-deprecated-functions.sql + online: true inputs: - from: /repo/batch/sql to: /io/sql From fa5e933f95993c2ff0537c248842c0abd8778bf5 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Mon, 28 Aug 2023 18:02:35 -0400 Subject: [PATCH 153/180] [auth] Fix the auth rest API for developers (#13515) I must have broken this during a recent refactor of the decorators. When making requests to an internal namespace, the default namespace's auth token is set in the `X-Hail-Internal-Authorization` header and the dev namespace's token is in the `Authorization` header. The dev namespace needs to know *not* to pick up the `X-Hail-Internal-Authorization` header. --- auth/auth/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/auth/auth.py b/auth/auth/auth.py index 76ae430cc6f..1f812815eda 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -770,7 +770,7 @@ async def userinfo(_, userdata: UserData) -> web.Response: async def get_session_id(request: web.Request) -> Optional[str]: - if 'X-Hail-Internal-Authorization' in request.headers: + if 'X-Hail-Internal-Authorization' in request.headers and DEFAULT_NAMESPACE == 'default': return maybe_parse_bearer_header(request.headers['X-Hail-Internal-Authorization']) if 'Authorization' in request.headers: From a3b7f0b0c17d89ea9b1005581e6cbfd9f90278d9 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 29 Aug 2023 08:53:00 -0400 Subject: [PATCH 154/180] [lint] Swap mypy for pyright (#13437) `pyright` is an alternative to `mypy` for type checking python. It's also a pretty solid language server. While they both adhere to the PEPs for type checking, they [have a few differences](https://github.com/microsoft/pyright/blob/main/docs/mypy-comparison.md#differences-between-pyright-and-mypy). That doc is worth a read, but the parts that I found most compelling are pyright's return-type inference that mypy doesn't do and that pyright differentiates between an `Unknown` type and an `Any` type. `mypy`, for the most part, treats variables as `Any` if it can't figure out what type they are, and as a result lets a lot of behaviors on `Any` variables slide. `pyright` tends to be much stricter (even when not on strict mode!) and while some of the assertions that I had to make here to appease `pyright` are a bit noisy, it's also pointed out a lot of areas where we can be stricter with our typing and then clean up code because some assertions are caught instead by the type system. It also did a good job informing of bad import practices like how `hl.utils` was not actually exported by the `hail` module but incidentally imported by some file in the repo. --------- Co-authored-by: Dan King --- .pre-commit-config.yaml | 11 ++++ Makefile | 4 +- auth/auth/auth.py | 21 +++---- auth/auth/flow.py | 6 +- batch/batch/batch.py | 5 +- batch/batch/cloud/azure/driver/driver.py | 3 +- batch/batch/cloud/azure/instance_config.py | 2 +- batch/batch/cloud/azure/resource_utils.py | 2 +- batch/batch/cloud/gcp/driver/driver.py | 3 +- batch/batch/driver/canceller.py | 7 ++- .../driver/instance_collection/job_private.py | 9 +-- .../batch/driver/instance_collection/pool.py | 12 ++-- batch/batch/front_end/front_end.py | 25 ++++---- batch/batch/inst_coll_config.py | 4 +- batch/batch/utils.py | 24 ++++++-- batch/batch/worker/worker.py | 8 +-- batch/test/test_batch.py | 6 +- build.yaml | 57 +++++++++++++++---- ci/bootstrap_create_accounts.py | 5 +- ci/ci/ci.py | 8 +-- ci/ci/github.py | 5 +- ci/test/test_ci.py | 1 + ci/wait-for.py | 2 +- docker/Dockerfile.hail-dev | 2 - gear/gear/auth.py | 3 + gear/gear/auth_utils.py | 2 +- gear/gear/database.py | 14 ++--- gear/gear/metrics.py | 2 +- gear/gear/time_limited_max_size_cache.py | 4 +- gear/pinned-requirements.txt | 2 +- hail/generate_splits.py | 5 +- hail/python/dev/pinned-requirements.txt | 31 +++++----- hail/python/dev/requirements.txt | 4 +- hail/python/hail/__init__.py | 2 + hail/python/hailtop/aiocloud/aioaws/fs.py | 2 +- hail/python/hailtop/aiocloud/aioazure/fs.py | 5 +- .../aiogoogle/client/storage_client.py | 6 +- .../hailtop/aiocloud/aiogoogle/user_config.py | 3 +- hail/python/hailtop/aiotools/fs/fs.py | 20 ++++--- .../hailtop/aiotools/weighted_semaphore.py | 4 +- hail/python/hailtop/batch/backend.py | 5 +- hail/python/hailtop/batch/batch.py | 9 ++- .../hailtop/batch/batch_pool_executor.py | 7 +-- hail/python/hailtop/batch/docs/conf.py | 2 +- hail/python/hailtop/batch/job.py | 23 ++++---- hail/python/hailtop/batch_client/aioclient.py | 19 ++++--- hail/python/hailtop/batch_client/client.py | 2 +- hail/python/hailtop/cleanup_gcr/__main__.py | 12 ++-- hail/python/hailtop/fs/fs.py | 5 +- .../hailtop/hailctl/batch/batch_cli_utils.py | 4 +- hail/python/hailtop/hailctl/batch/cli.py | 5 +- .../hailtop/hailctl/batch/initialize.py | 1 + .../hailctl/config/config_variables.py | 2 +- hail/python/hailtop/hailctl/describe.py | 4 +- hail/python/hailtop/httpx.py | 18 +++--- hail/python/hailtop/utils/__init__.py | 5 +- .../python/hailtop/utils/rich_progress_bar.py | 2 +- hail/python/hailtop/utils/time.py | 9 ++- hail/python/hailtop/utils/utils.py | 34 +++++------ .../python/hailtop/utils/validate/validate.py | 4 +- hail/python/test/hail/utils/test_utils.py | 2 +- hail/python/test/hailtop/batch/test_batch.py | 47 ++++++++++----- .../hailtop/batch/test_batch_pool_executor.py | 3 +- .../test/hailtop/inter_cloud/test_copy.py | 12 ++-- .../test/hailtop/inter_cloud/test_fs.py | 3 +- hail/python/test/hailtop/test_aiogoogle.py | 4 +- hail/python/test/hailtop/utils/test_utils.py | 2 +- hail/scripts/assert_pypi_has_room.py | 3 +- hail/scripts/test_requester_pays_parsing.py | 13 +++-- monitoring/monitoring/monitoring.py | 10 ++-- pyproject.toml | 17 ++++++ setup.cfg | 4 -- website/website/website.py | 7 ++- 73 files changed, 387 insertions(+), 253 deletions(-) delete mode 100644 setup.cfg diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9670cf9789d..ef9806b31b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,16 @@ --- +default_install_hook_types: [pre-commit, pre-push] repos: + - repo: local + hooks: + - id: pyright + name: pyright + entry: pyright + language: system + types: [python] + require_serial: true + stages: + - pre-push - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.3.0 hooks: diff --git a/Makefile b/Makefile index 7b8aaaab905..9eb6236ca08 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ check-all: check-hail check-services check-hail-fast: ruff check hail/python/hail ruff check hail/python/hailtop - $(PYTHON) -m mypy --config-file setup.cfg hail/python/hailtop + $(PYTHON) -m pyright hail/python/hailtop .PHONY: pylint-hailtop pylint-hailtop: @@ -55,7 +55,7 @@ pylint-%: .PHONY: check-%-fast check-%-fast: ruff check $* - $(PYTHON) -m mypy --config-file setup.cfg $* + $(PYTHON) -m pyright $* $(PYTHON) -m black $* --check --diff curlylint $* cd $* && bash ../check-sql.sh diff --git a/auth/auth/auth.py b/auth/auth/auth.py index 1f812815eda..9c6283d0b33 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -3,6 +3,7 @@ import logging import os import re +import typing from functools import wraps from typing import List, NoReturn, Optional @@ -102,10 +103,10 @@ async def wrapped(request: web.Request) -> web.StreamResponse: return wrapped -async def user_from_login_id(db, login_id): +async def user_from_login_id(db: Database, login_id: str) -> Optional[UserData]: users = [x async for x in db.select_and_fetchall("SELECT * FROM users WHERE login_id = %s;", login_id)] if len(users) == 1: - return users[0] + return typing.cast(UserData, users[0]) assert len(users) == 0, users return None @@ -284,17 +285,11 @@ async def _wait_websocket(request, login_id): try: count = 0 - while count < 10: - try: - user = await user_from_login_id(db, login_id) - assert user - if user['state'] != 'creating': - log.info(f"user {user['username']} is no longer creating") - break - except asyncio.CancelledError: - raise - except Exception: # pylint: disable=broad-except - log.exception(f"/creating/wait: error while updating status for user {user['username']}") + user = await user_from_login_id(db, login_id) + assert user + while count < 10 and user['state'] == 'creating': + user = await user_from_login_id(db, login_id) + assert user await asyncio.sleep(1) count += 1 diff --git a/auth/auth/flow.py b/auth/auth/flow.py index 6f09ef18a20..9fb19a50345 100644 --- a/auth/auth/flow.py +++ b/auth/auth/flow.py @@ -1,7 +1,7 @@ import abc import json import urllib.parse -from typing import ClassVar, List +from typing import Any, ClassVar, List, Mapping import aiohttp.web import google.auth.transport.requests @@ -13,7 +13,7 @@ class FlowResult: - def __init__(self, login_id: str, email: str, token: dict): + def __init__(self, login_id: str, email: str, token: Mapping[Any, Any]): self.login_id = login_id self.email = email self.token = token @@ -66,7 +66,7 @@ def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> Flo flow.redirect_uri = flow_dict['callback_uri'] flow.fetch_token(code=request.query['code']) token = google.oauth2.id_token.verify_oauth2_token( - flow.credentials.id_token, google.auth.transport.requests.Request() + flow.credentials.id_token, google.auth.transport.requests.Request() # type: ignore ) email = token['email'] return FlowResult(email, email, token) diff --git a/batch/batch/batch.py b/batch/batch/batch.py index 19b7f092b64..52dc7d2e949 100644 --- a/batch/batch/batch.py +++ b/batch/batch/batch.py @@ -1,5 +1,6 @@ import json import logging +from typing import Any, Dict, Optional from gear import transaction from hailtop.utils import humanize_timedelta_msecs, time_msecs_str @@ -11,7 +12,7 @@ log = logging.getLogger('batch') -def batch_record_to_dict(record): +def batch_record_to_dict(record: Dict[str, Any]) -> Dict[str, Any]: if record['state'] == 'open': state = 'open' elif record['n_failed'] > 0: @@ -66,7 +67,7 @@ def _time_msecs_str(t): return d -def job_record_to_dict(record, name): +def job_record_to_dict(record: Dict[str, Any], name: Optional[str]) -> Dict[str, Any]: format_version = BatchFormatVersion(record['format_version']) db_status = record['status'] diff --git a/batch/batch/cloud/azure/driver/driver.py b/batch/batch/cloud/azure/driver/driver.py index 9256e7f8033..61a5b0adc8f 100644 --- a/batch/batch/cloud/azure/driver/driver.py +++ b/batch/batch/cloud/azure/driver/driver.py @@ -2,6 +2,7 @@ import json import logging import os +from typing import Dict from gear import Database from gear.cloud_config import get_azure_config @@ -45,7 +46,7 @@ async def create( region_args, ) - db_regions = { + db_regions: Dict[str, int] = { record['region']: record['region_id'] async for record in db.select_and_fetchall('SELECT region_id, region from regions') } diff --git a/batch/batch/cloud/azure/instance_config.py b/batch/batch/cloud/azure/instance_config.py index c70d5a58fd7..e14123a9bb3 100644 --- a/batch/batch/cloud/azure/instance_config.py +++ b/batch/batch/cloud/azure/instance_config.py @@ -35,7 +35,7 @@ def create( else: data_disk_resource = AzureStaticSizedDiskResource.create(product_versions, 'P', data_disk_size_gb, location) - resources = filter_none( + resources: List[AzureResource] = filter_none( [ AzureVMResource.create(product_versions, machine_type, preemptible, location), AzureStaticSizedDiskResource.create(product_versions, 'E', boot_disk_size_gb, location), diff --git a/batch/batch/cloud/azure/resource_utils.py b/batch/batch/cloud/azure/resource_utils.py index 9b73073c5a0..5a85d86edd3 100644 --- a/batch/batch/cloud/azure/resource_utils.py +++ b/batch/batch/cloud/azure/resource_utils.py @@ -100,7 +100,7 @@ def azure_disk_from_storage_in_gib(disk_type: str, storage_in_gib: int) -> Optio index = disks.bisect_key_left(storage_in_gib) if index == len(disks): return None - return disks[index] + return disks[index] # type: ignore class MachineTypeParts: diff --git a/batch/batch/cloud/gcp/driver/driver.py b/batch/batch/cloud/gcp/driver/driver.py index 075400bb774..2851962406d 100644 --- a/batch/batch/cloud/gcp/driver/driver.py +++ b/batch/batch/cloud/gcp/driver/driver.py @@ -1,4 +1,5 @@ import asyncio +from typing import Dict from gear import Database from gear.cloud_config import get_gcp_config @@ -42,7 +43,7 @@ async def create( region_args, ) - db_regions = { + db_regions: Dict[str, int] = { record['region']: record['region_id'] async for record in db.select_and_fetchall('SELECT region_id, region from regions') } diff --git a/batch/batch/driver/canceller.py b/batch/batch/driver/canceller.py index 9cfdcc5ed87..b939c8e9fef 100644 --- a/batch/batch/driver/canceller.py +++ b/batch/batch/driver/canceller.py @@ -1,5 +1,6 @@ import asyncio import logging +from typing import Any, AsyncIterator, Dict from gear import Database from hailtop import aiotools @@ -92,7 +93,7 @@ async def cancel_cancelled_ready_jobs_loop_body(self): for user, user_n_jobs in user_n_cancelled_ready_jobs.items() } - async def user_cancelled_ready_jobs(user, remaining): + async def user_cancelled_ready_jobs(user, remaining) -> AsyncIterator[Dict[str, Any]]: async for batch in self.db.select_and_fetchall( ''' SELECT batches.id, batches_cancelled.id IS NOT NULL AS cancelled @@ -180,7 +181,7 @@ async def cancel_cancelled_creating_jobs_loop_body(self): for user, user_n_jobs in user_n_cancelled_creating_jobs.items() } - async def user_cancelled_creating_jobs(user, remaining): + async def user_cancelled_creating_jobs(user, remaining) -> AsyncIterator[Dict[str, Any]]: async for batch in self.db.select_and_fetchall( ''' SELECT batches.id @@ -277,7 +278,7 @@ async def cancel_cancelled_running_jobs_loop_body(self): for user, user_n_jobs in user_n_cancelled_running_jobs.items() } - async def user_cancelled_running_jobs(user, remaining): + async def user_cancelled_running_jobs(user, remaining) -> AsyncIterator[Dict[str, Any]]: async for batch in self.db.select_and_fetchall( ''' SELECT batches.id diff --git a/batch/batch/driver/instance_collection/job_private.py b/batch/batch/driver/instance_collection/job_private.py index 91c97860480..44a021fa08a 100644 --- a/batch/batch/driver/instance_collection/job_private.py +++ b/batch/batch/driver/instance_collection/job_private.py @@ -3,7 +3,7 @@ import logging import random import traceback -from typing import Dict, List, Tuple +from typing import Any, AsyncIterator, Dict, List, Tuple import sortedcontainers @@ -271,7 +271,7 @@ def allocate_jobs(user, mark): lowest_total = None if pending_users_by_live_jobs: - lowest_running_user = pending_users_by_live_jobs[0] + lowest_running_user: str = pending_users_by_live_jobs[0] # type: ignore lowest_running = user_live_jobs[lowest_running_user] if lowest_running == mark: pending_users_by_live_jobs.remove(lowest_running_user) @@ -279,7 +279,7 @@ def allocate_jobs(user, mark): continue if allocating_users_by_total_jobs: - lowest_total_user = allocating_users_by_total_jobs[0] + lowest_total_user: str = allocating_users_by_total_jobs[0] # type: ignore lowest_total = user_total_jobs[lowest_total_user] if lowest_total == mark: allocating_users_by_total_jobs.remove(lowest_total_user) @@ -348,7 +348,7 @@ async def create_instances_loop_body(self): for user, resources in user_resources.items() } - async def user_runnable_jobs(user, remaining): + async def user_runnable_jobs(user, remaining) -> AsyncIterator[Dict[str, Any]]: async for batch in self.db.select_and_fetchall( ''' SELECT batches.id, batches_cancelled.id IS NOT NULL AS cancelled, userdata, user, format_version @@ -448,6 +448,7 @@ async def create_instance_with_error_handling( else: regions = regions_bits_rep_to_regions(regions_bits_rep, self.app['regions']) + assert machine_spec instance, total_resources_on_instance = await self.create_instance(machine_spec, regions) log.info(f'created {instance} for {(batch_id, job_id)}') await mark_job_creating( diff --git a/batch/batch/driver/instance_collection/pool.py b/batch/batch/driver/instance_collection/pool.py index 8bce99a71ec..e3e3e019a06 100644 --- a/batch/batch/driver/instance_collection/pool.py +++ b/batch/batch/driver/instance_collection/pool.py @@ -2,7 +2,7 @@ import logging import random from collections import defaultdict -from typing import Dict, List, Tuple +from typing import Dict, List, Optional, Tuple import prometheus_client as pc import sortedcontainers @@ -201,10 +201,10 @@ def adjust_for_add_instance(self, instance): if instance.state == 'active' and instance.failed_request_count <= 1: self.healthy_instances_by_free_cores.add(instance) - def get_instance(self, cores_mcpu: int, regions: List[str]): + def get_instance(self, cores_mcpu: int, regions: List[str]) -> Optional[Instance]: i = self.healthy_instances_by_free_cores.bisect_key_left(cores_mcpu) while i < len(self.healthy_instances_by_free_cores): - instance = self.healthy_instances_by_free_cores[i] + instance: Instance = self.healthy_instances_by_free_cores[i] # type: ignore assert cores_mcpu <= instance.free_cores_mcpu if instance.region in regions and instance.version == INSTANCE_VERSION: return instance @@ -372,7 +372,7 @@ async def regions_to_ready_cores_mcpu_from_estimated_job_queue(self) -> List[Tup query_name='get_job_queue_head', ) - def extract_regions(regions_bits_rep): + def extract_regions(regions_bits_rep: int): if regions_bits_rep is None: return self.all_supported_regions return regions_bits_rep_to_regions(regions_bits_rep, self.app['regions']) @@ -539,7 +539,7 @@ def allocate_cores(user, mark): lowest_total = None if pending_users_by_running_cores: - lowest_running_user = pending_users_by_running_cores[0] + lowest_running_user: str = pending_users_by_running_cores[0] # type: ignore lowest_running = user_running_cores_mcpu[lowest_running_user] if lowest_running == mark: pending_users_by_running_cores.remove(lowest_running_user) @@ -547,7 +547,7 @@ def allocate_cores(user, mark): continue if allocating_users_by_total_cores: - lowest_total_user = allocating_users_by_total_cores[0] + lowest_total_user: str = allocating_users_by_total_cores[0] # type: ignore lowest_total = user_total_cores_mcpu[lowest_total_user] if lowest_total == mark: allocating_users_by_total_cores.remove(lowest_total_user) diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index 7bae14fc1bf..a701223c9ca 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -285,10 +285,9 @@ async def _get_jobs(request, batch_id: int, version: int, q: str, last_job_id: O jobs, last_job_id = await _query_batch_jobs(request, batch_id, version, q, last_job_id) - resp = {'jobs': jobs} if last_job_id is not None: - resp['last_job_id'] = last_job_id - return resp + return {'jobs': jobs, 'last_job_id': last_job_id} + return {'jobs': jobs} @routes.get('/api/v1alpha/batches/{batch_id}/jobs') @@ -428,7 +427,7 @@ async def _get_job_log(app, batch_id, job_id) -> Dict[str, Optional[bytes]]: return dict(zip(containers, logs)) -async def _get_job_resource_usage(app, batch_id, job_id): +async def _get_job_resource_usage(app, batch_id, job_id) -> Optional[Dict[str, Optional[pd.DataFrame]]]: record = await _get_job_record(app, batch_id, job_id) client_session: httpx.ClientSession = app['client_session'] @@ -471,7 +470,7 @@ async def _read_resource_usage_from_cloud_storage(task): return dict(await asyncio.gather(*[_read_resource_usage_from_cloud_storage(task) for task in tasks])) -async def _get_jvm_profile(app, batch_id, job_id): +async def _get_jvm_profile(app: web.Application, batch_id: int, job_id: int) -> Optional[str]: record = await _get_job_record(app, batch_id, job_id) file_store: FileStore = app['file_store'] @@ -651,10 +650,10 @@ async def get_batches_v1(request, userdata): # pylint: disable=unused-argument result = await _handle_api_error(_query_batches, request, user, q, 1, last_batch_id) assert result is not None batches, last_batch_id = result - body = {'batches': batches} + if last_batch_id is not None: - body['last_batch_id'] = last_batch_id - return json_response(body) + return json_response({'batches': batches, 'last_batch_id': last_batch_id}) + return json_response({'batches': batches}) @routes.get('/api/v2alpha/batches') @@ -667,10 +666,10 @@ async def get_batches_v2(request, userdata): # pylint: disable=unused-argument result = await _handle_api_error(_query_batches, request, user, q, 2, last_batch_id) assert result is not None batches, last_batch_id = result - body = {'batches': batches} + if last_batch_id is not None: - body['last_batch_id'] = last_batch_id - return json_response(body) + return json_response({'batches': batches, 'last_batch_id': last_batch_id}) + return json_response({'batches': batches}) def check_service_account_permissions(user, sa): @@ -2175,7 +2174,7 @@ async def ui_get_job(request, userdata, batch_id): @routes.get('/batches/{batch_id}/jobs/{job_id}/log/{container}') @web_billing_project_users_only() @catch_ui_error_in_dev -async def ui_get_job_log(request: web.Request, _, batch_id: int) -> web.Response: +async def ui_get_job_log(request: web.Request, _, batch_id: int) -> web.StreamResponse: return await get_job_container_log(request, batch_id) @@ -2875,7 +2874,7 @@ async def on_startup(app): app['frozen'] = row['frozen'] - regions = { + regions: Dict[str, int] = { record['region']: record['region_id'] async for record in db.select_and_fetchall('SELECT region_id, region from regions') } diff --git a/batch/batch/inst_coll_config.py b/batch/batch/inst_coll_config.py index ee3ef8c4c9d..56aa0052c0b 100644 --- a/batch/batch/inst_coll_config.py +++ b/batch/batch/inst_coll_config.py @@ -345,7 +345,9 @@ def select_pool_from_cost(self, cloud, cores_mcpu, memory_bytes, storage_bytes, if max_regional_maybe_cost is None or maybe_cost > max_regional_maybe_cost: max_regional_maybe_cost = maybe_cost - if optimal_cost is None or max_regional_maybe_cost < optimal_cost: + if optimal_cost is None or ( + max_regional_maybe_cost is not None and max_regional_maybe_cost < optimal_cost + ): optimal_cost = max_regional_maybe_cost optimal_result = (pool.name, maybe_cores_mcpu, maybe_memory_bytes, maybe_storage_gib) return optimal_result diff --git a/batch/batch/utils.py b/batch/batch/utils.py index e22ccca37c8..d82f94955fd 100644 --- a/batch/batch/utils.py +++ b/batch/batch/utils.py @@ -3,11 +3,11 @@ import secrets from collections import deque from functools import wraps -from typing import Deque, Set, Tuple +from typing import Any, Deque, Dict, List, Optional, Set, Tuple, overload from aiohttp import web -from gear import maybe_parse_bearer_header +from gear import Database, maybe_parse_bearer_header from hailtop.utils import secret_alnum_string log = logging.getLogger('utils') @@ -133,7 +133,7 @@ def __repr__(self): return f'global {self._global_counter}' -async def query_billing_projects_with_cost(db, user=None, billing_project=None): +async def query_billing_projects_with_cost(db, user=None, billing_project=None) -> List[Dict[str, Any]]: where_conditions = ["billing_projects.`status` != 'deleted'"] args = [] @@ -186,7 +186,9 @@ async def query_billing_projects_with_cost(db, user=None, billing_project=None): return billing_projects -async def query_billing_projects_without_cost(db, user=None, billing_project=None): +async def query_billing_projects_without_cost( + db: Database, user: Optional[str] = None, billing_project: Optional[str] = None +) -> List[Dict[str, Any]]: where_conditions = ["billing_projects.`status` != 'deleted'"] args = [] @@ -242,7 +244,19 @@ def regions_to_bits_rep(selected_regions, all_regions_mapping): return result -def regions_bits_rep_to_regions(regions_bits_rep, all_regions_mapping): +@overload +def regions_bits_rep_to_regions(regions_bits_rep: None, all_regions_mapping: Dict[str, int]) -> None: + ... + + +@overload +def regions_bits_rep_to_regions(regions_bits_rep: int, all_regions_mapping: Dict[str, int]) -> List[str]: + ... + + +def regions_bits_rep_to_regions( + regions_bits_rep: Optional[int], all_regions_mapping: Dict[str, int] +) -> Optional[List[str]]: if regions_bits_rep is None: return None result = [] diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index 69636d8b939..a758ccd7730 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -1,7 +1,7 @@ import abc import asyncio import base64 -import concurrent +import concurrent.futures import errno import json import logging @@ -144,7 +144,7 @@ def compose(auth: Union[MutableMapping, str, bytes], registry_addr: Optional[str # We patched aiodocker's utility function `compose_auth_header` because it does not base64 encode strings # in urlsafe mode which is required for Azure's credentials. # https://github.com/aio-libs/aiodocker/blob/17e08844461664244ea78ecd08d1672b1779acc1/aiodocker/utils.py#L297 -aiodocker.images.compose_auth_header = compose_auth_header_urlsafe(aiodocker.images.compose_auth_header) +aiodocker.images.compose_auth_header = compose_auth_header_urlsafe(aiodocker.images.compose_auth_header) # type: ignore configure_logging() @@ -1645,7 +1645,7 @@ async def mark_complete(self, mjs_fut: asyncio.Task): # start_time: int, # end_time: int, # resources: list of dict, {name: str, quantity: int} - # region: str + # region: str # type: ignore # } def status(self): status = { @@ -2899,7 +2899,7 @@ def __init__(self, client_session: httpx.ClientSession): self.cloudfuse_mount_manager = ReadOnlyCloudfuseManager() self._jvm_initializer_task = asyncio.create_task(self._initialize_jvms()) - self._jvms: SortedSet[JVM] = SortedSet([], key=lambda jvm: jvm.n_cores) + self._jvms = SortedSet([], key=lambda jvm: jvm.n_cores) async def _initialize_jvms(self): assert instance_config diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 0128979fa92..3cd0fabc404 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -1593,9 +1593,9 @@ def test_update_with_always_run(client: BatchClient): wait_status = j1._wait_for_states('Running') if wait_status['state'] != 'Running': - assert False, str(j1.status(), b.debug_info()) + assert False, str((j1.status(), b.debug_info())) - assert j2.is_pending(), str(j2.status(), b.debug_info()) + assert j2.is_pending(), str((j2.status(), b.debug_info())) b.cancel() j2.wait() @@ -1616,7 +1616,7 @@ def test_update_jobs_are_not_serialized(client: BatchClient): wait_status = j1._wait_for_states('Running') if wait_status['state'] != 'Running': - assert False, str(j1.status(), b.debug_info()) + assert False, str((j1.status(), b.debug_info())) b.cancel() diff --git a/build.yaml b/build.yaml index 037806dc2e0..f935809d99e 100644 --- a/build.yaml +++ b/build.yaml @@ -152,10 +152,6 @@ steps: inputs: - from: /repo/docker/Dockerfile.base to: /io/repo/docker/Dockerfile.base - - from: /repo/pylintrc - to: /io/repo/pylintrc - - from: /repo/setup.cfg - to: /io/repo/setup.cfg dependsOn: - hail_ubuntu_image - merge_code @@ -1403,14 +1399,54 @@ steps: dependsOn: - hailgenetics_hail_image - merge_code + - kind: buildImage2 + name: hail_linting_image + contextPath: /io/repo + dockerFile: + inline: | + FROM {{ hail_ubuntu_image.image }} + RUN hail-apt-get-install make + COPY hail/python/pinned-requirements.txt hail-requirements.txt + COPY hail/python/dev/pinned-requirements.txt dev-requirements.txt + COPY gear/pinned-requirements.txt gear-requirements.txt + COPY web_common/pinned-requirements.txt web_common-requirements.txt + COPY auth/pinned-requirements.txt auth-requirements.txt + COPY batch/pinned-requirements.txt batch-requirements.txt + COPY ci/pinned-requirements.txt ci-requirements.txt + RUN python3 -m pip install \ + -r hail-requirements.txt \ + -r dev-requirements.txt \ + -r gear-requirements.txt \ + -r web_common-requirements.txt \ + -r auth-requirements.txt \ + -r batch-requirements.txt \ + -r ci-requirements.txt + publishAs: linting + inputs: + - from: /repo/hail/python/pinned-requirements.txt + to: /io/repo/hail/python/pinned-requirements.txt + - from: /repo/hail/python/dev/pinned-requirements.txt + to: /io/repo/hail/python/dev/pinned-requirements.txt + - from: /repo/gear/pinned-requirements.txt + to: /io/repo/gear/pinned-requirements.txt + - from: /repo/web_common/pinned-requirements.txt + to: /io/repo/web_common/pinned-requirements.txt + - from: /repo/auth/pinned-requirements.txt + to: /io/repo/auth/pinned-requirements.txt + - from: /repo/batch/pinned-requirements.txt + to: /io/repo/batch/pinned-requirements.txt + - from: /repo/ci/pinned-requirements.txt + to: /io/repo/ci/pinned-requirements.txt + dependsOn: + - merge_code + - hail_ubuntu_image - kind: runImage name: check_services image: - valueFrom: hail_dev_image.image + valueFrom: hail_linting_image.image script: | set -ex cd /io/repo - make install-dev-requirements {% if 'target_sha' in code %} export HAIL_TARGET_SHA={{ code.target_sha }} {% endif %} @@ -1419,12 +1455,12 @@ steps: - from: /repo to: /io/repo dependsOn: - - hail_dev_image + - hail_linting_image - merge_code - kind: runImage name: check_hail image: - valueFrom: hail_dev_image.image + valueFrom: hail_linting_image.image script: | set -ex cd /io/repo @@ -1434,8 +1470,6 @@ steps: to: /io/repo/Makefile - from: /repo/pylintrc to: /io/repo/pylintrc - - from: /repo/setup.cfg - to: /io/repo/setup.cfg - from: /repo/pyproject.toml to: /io/repo/pyproject.toml - from: /repo/hail/python @@ -1443,7 +1477,7 @@ steps: - from: /repo/config.mk to: /io/repo/config.mk dependsOn: - - hail_dev_image + - hail_linting_image - merge_code - kind: runImage name: get_pip_versioned_docs @@ -2704,7 +2738,6 @@ steps: cp /io/repo/tls/create_certs.py ./ci/test/resources/ cp /io/repo/tls/create_test_db_config.sh ./ci/test/resources/ cp /io/repo/pylintrc ./ - cp /io/repo/setup.cfg ./ cp /io/repo/pyproject.toml ./ cp -R /io/repo/docker ./ cp -R /io/repo/gear ./ diff --git a/ci/bootstrap_create_accounts.py b/ci/bootstrap_create_accounts.py index abece32ada8..baefee65b28 100644 --- a/ci/bootstrap_create_accounts.py +++ b/ci/bootstrap_create_accounts.py @@ -5,12 +5,13 @@ import base64 # noqa: E402 pylint: disable=wrong-import-position import json # noqa: E402 pylint: disable=wrong-import-position import os # noqa: E402 pylint: disable=wrong-import-position +from typing import Optional # noqa: E402 pylint: disable=wrong-import-position import kubernetes_asyncio.client # noqa: E402 pylint: disable=wrong-import-position import kubernetes_asyncio.config # noqa: E402 pylint: disable=wrong-import-position from auth.driver.driver import create_user # noqa: E402 pylint: disable=wrong-import-position -from gear import Database, transaction # noqa: E402 pylint: disable=wrong-import-position +from gear import Database, Transaction, transaction # noqa: E402 pylint: disable=wrong-import-position from gear.clients import get_identity_client # noqa: E402 pylint: disable=wrong-import-position from gear.cloud_config import get_global_config # noqa: E402 pylint: disable=wrong-import-position from hailtop.utils import async_to_blocking # noqa: E402 pylint: disable=wrong-import-position,ungrouped-imports @@ -25,7 +26,7 @@ async def insert_user_if_not_exists(app, username, login_id, is_developer, is_se k8s_client = app['k8s_client'] @transaction(db) - async def insert(tx): + async def insert(tx: Transaction) -> Optional[int]: row = await tx.execute_and_fetchone('SELECT id, state FROM users where username = %s;', (username,)) if row: if row['state'] == 'active': diff --git a/ci/ci/ci.py b/ci/ci/ci.py index 3b3770e98d3..5d8b4a5a586 100644 --- a/ci/ci/ci.py +++ b/ci/ci/ci.py @@ -35,7 +35,7 @@ from hailtop.config import get_deploy_config from hailtop.hail_logging import AccessLogger from hailtop.tls import internal_server_ssl_context -from hailtop.utils import collect_agen, humanize_timedelta_msecs, periodically_call, retry_transient_errors +from hailtop.utils import collect_aiter, humanize_timedelta_msecs, periodically_call, retry_transient_errors from web_common import render_template, set_message, setup_aiohttp_jinja2, setup_common_static_routes from .constants import AUTHORIZED_USERS, TEAMS @@ -176,7 +176,7 @@ async def get_pr(request: web.Request, userdata: UserData) -> web.Response: if batch: if isinstance(batch, Batch): status = await batch.last_known_status() - jobs = await collect_agen(batch.jobs()) + jobs = await collect_aiter(batch.jobs()) for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) page_context['batch'] = status @@ -250,7 +250,7 @@ async def get_batch(request, userdata): batch_client = request.app['batch_client'] b = await batch_client.get_batch(batch_id) status = await b.last_known_status() - jobs = await collect_agen(b.jobs()) + jobs = await collect_aiter(b.jobs()) for j in jobs: j['duration'] = humanize_timedelta_msecs(j['duration']) wb = get_maybe_wb_for_batch(b) @@ -432,7 +432,7 @@ async def get_failure_information(batch): if isinstance(batch, MergeFailureBatch): exc = batch.exception return traceback.format_exception(type(exc), value=exc, tb=exc.__traceback__) - jobs = await collect_agen(batch.jobs()) + jobs = await collect_aiter(batch.jobs()) async def fetch_job_and_log(j): full_job = await batch_client.get_job(j['batch_id'], j['job_id']) diff --git a/ci/ci/github.py b/ci/ci/github.py index 747f3f75721..32f03a9f0ea 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -11,6 +11,7 @@ from typing import Any, Dict, List, Optional, Sequence, Set, Union import aiohttp +import aiohttp.client_exceptions import gidgethub import prometheus_client as pc # type: ignore import zulip @@ -909,7 +910,9 @@ async def _heal(self, app, batch_client, gh): if pr.review_state == 'approved' and not pr.build_failed_on_at_least_one_platform(): pri = pr.merge_priority() is_authorized = await pr.authorized(db) - if is_authorized and (not merge_candidate or pri > merge_candidate_pri): + if is_authorized and ( + not merge_candidate or (merge_candidate_pri is not None and pri > merge_candidate_pri) + ): merge_candidate = pr merge_candidate_pri = pri diff --git a/ci/test/test_ci.py b/ci/test/test_ci.py index 112afecef64..1d6045d33cf 100644 --- a/ci/test/test_ci.py +++ b/ci/test/test_ci.py @@ -22,6 +22,7 @@ async def test_deploy(): async def wait_forever(): deploy_state = None + deploy_status = None failure_information = None while deploy_state is None: deploy_statuses = await retry_transient_errors( diff --git a/ci/wait-for.py b/ci/wait-for.py index 90c69a67da4..22ed7967cd2 100644 --- a/ci/wait-for.py +++ b/ci/wait-for.py @@ -32,7 +32,7 @@ async def wait_for_pod_complete(v1, namespace, name): else: print('error: a container failed') sys.exit(1) - except client.rest.ApiException as exc: + except client.ApiException as exc: if exc.status == 404: print('info: 404', file=sys.stderr) else: diff --git a/docker/Dockerfile.hail-dev b/docker/Dockerfile.hail-dev index 41359f02cb8..6f575275af7 100644 --- a/docker/Dockerfile.hail-dev +++ b/docker/Dockerfile.hail-dev @@ -1,6 +1,4 @@ FROM {{ hailgenetics_hail_image.image }} -RUN hail-apt-get-install make - COPY hail/python/dev/pinned-requirements.txt dev-requirements.txt RUN hail-pip-install -r dev-requirements.txt diff --git a/gear/gear/auth.py b/gear/gear/auth.py index 79057c4bd49..3591cfeead7 100644 --- a/gear/gear/auth.py +++ b/gear/gear/auth.py @@ -24,7 +24,10 @@ class UserData(TypedDict): + id: int + state: str username: str + login_id: str namespace_name: str is_developer: bool is_service_account: bool diff --git a/gear/gear/auth_utils.py b/gear/gear/auth_utils.py index 69dfa00e343..c04fe41bb38 100644 --- a/gear/gear/auth_utils.py +++ b/gear/gear/auth_utils.py @@ -19,7 +19,7 @@ async def insert_user(db, spec): # 2592000s = 30d -async def create_session(db: Database, user_id: str, max_age_secs: Optional[int] = 2592000) -> str: +async def create_session(db: Database, user_id: int, max_age_secs: Optional[int] = 2592000) -> str: session_id = session_id_encode_to_str(secrets.token_bytes(32)) await db.just_execute( 'INSERT INTO sessions (session_id, user_id, max_age_secs) VALUES (%s, %s, %s);', diff --git a/gear/gear/database.py b/gear/gear/database.py index 065d760af72..e294044f336 100644 --- a/gear/gear/database.py +++ b/gear/gear/database.py @@ -4,7 +4,7 @@ import os import ssl import traceback -from typing import Awaitable, Callable, Optional, TypeVar +from typing import Any, AsyncIterator, Awaitable, Callable, Dict, Optional, TypeVar import aiomysql import kubernetes_asyncio.client @@ -91,11 +91,11 @@ async def resolve_test_db_endpoint(sql_config: SQLConfig) -> SQLConfig: await kubernetes_asyncio.config.load_kube_config() async with kubernetes_asyncio.client.ApiClient() as api: client = kubernetes_asyncio.client.CoreV1Api(api) - db_service = await client.read_namespaced_service(service_name, namespace) - db_pod = await client.read_namespaced_pod(f'{db_service.spec.selector["app"]}-0', namespace) + db_service = await client.read_namespaced_service(service_name, namespace) # type: ignore + db_pod = await client.read_namespaced_pod(f'{db_service.spec.selector["app"]}-0', namespace) # type: ignore sql_config_dict = sql_config.to_dict() - sql_config_dict['host'] = db_pod.status.host_ip - sql_config_dict['port'] = db_service.spec.ports[0].node_port + sql_config_dict['host'] = db_pod.status.host_ip # type: ignore + sql_config_dict['port'] = db_service.spec.ports[0].node_port # type: ignore return SQLConfig.from_dict(sql_config_dict) @@ -243,7 +243,7 @@ async def execute_and_fetchone(self, sql, args=None, query_name=None): await cursor.execute(sql, args) return await cursor.fetchone() - async def execute_and_fetchall(self, sql, args=None, query_name=None): + async def execute_and_fetchall(self, sql: str, args=None, query_name=None) -> AsyncIterator[Dict[str, Any]]: assert self.conn async with self.conn.cursor() as cursor: if query_name is None: @@ -258,7 +258,7 @@ async def execute_and_fetchall(self, sql, args=None, query_name=None): for row in rows: yield row - async def execute_insertone(self, sql, args=None, *, query_name=None): + async def execute_insertone(self, sql, args=None, *, query_name=None) -> Optional[int]: assert self.conn async with self.conn.cursor() as cursor: if query_name is None: diff --git a/gear/gear/metrics.py b/gear/gear/metrics.py index af6608733eb..f413e4b0f76 100644 --- a/gear/gear/metrics.py +++ b/gear/gear/metrics.py @@ -25,7 +25,7 @@ async def monitor_endpoints_middleware(request, handler): verb = request.method CONCURRENT_REQUESTS.labels(endpoint=endpoint, verb=verb).inc() try: - response = await prom_async_time(REQUEST_TIME.labels(endpoint=endpoint, verb=verb), handler(request)) + response = await prom_async_time(REQUEST_TIME.labels(endpoint=endpoint, verb=verb), handler(request)) # type: ignore REQUEST_COUNT.labels(endpoint=endpoint, verb=verb, status=response.status).inc() return response except web.HTTPException as e: diff --git a/gear/gear/time_limited_max_size_cache.py b/gear/gear/time_limited_max_size_cache.py index d8e1f71645b..b30e30b3756 100644 --- a/gear/gear/time_limited_max_size_cache.py +++ b/gear/gear/time_limited_max_size_cache.py @@ -63,7 +63,7 @@ async def lookup(self, k: T) -> U: self._futures[k] = asyncio.create_task(self.load(k)) try: - v = await prom_async_time(CACHE_LOAD_LATENCY.labels(cache_name=self.cache_name), self._futures[k]) + v = await prom_async_time(CACHE_LOAD_LATENCY.labels(cache_name=self.cache_name), self._futures[k]) # type: ignore finally: del self._futures[k] @@ -90,5 +90,5 @@ def _over_capacity(self) -> bool: return len(self._keys_by_expiry) > self.num_slots def _evict_oldest(self) -> None: - oldest_key = self._keys_by_expiry[0] + oldest_key: T = self._keys_by_expiry[0] # type: ignore self._remove(oldest_key) diff --git a/gear/pinned-requirements.txt b/gear/pinned-requirements.txt index 81bfb533edb..414d4efc818 100644 --- a/gear/pinned-requirements.txt +++ b/gear/pinned-requirements.txt @@ -71,7 +71,7 @@ google-api-core==2.11.1 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # google-api-python-client -google-api-python-client==2.96.0 +google-api-python-client==2.97.0 # via google-cloud-profiler google-auth==2.22.0 # via diff --git a/hail/generate_splits.py b/hail/generate_splits.py index b22f92ed943..4206a8dc2c7 100644 --- a/hail/generate_splits.py +++ b/hail/generate_splits.py @@ -1,9 +1,12 @@ import os import random import subprocess as sp +from typing import List, TypeVar +T = TypeVar("T") -def partition(k, ls): + +def partition(k: int, ls: List[T]) -> List[List[T]]: assert k > 0 assert ls diff --git a/hail/python/dev/pinned-requirements.txt b/hail/python/dev/pinned-requirements.txt index bbac9d36684..86a75fce1f6 100644 --- a/hail/python/dev/pinned-requirements.txt +++ b/hail/python/dev/pinned-requirements.txt @@ -8,7 +8,7 @@ alabaster==0.7.13 # via sphinx anyio==3.7.1 # via jupyter-server -argon2-cffi==21.3.0 +argon2-cffi==23.1.0 # via jupyter-server argon2-cffi-bindings==21.2.0 # via argon2-cffi @@ -95,7 +95,7 @@ executing==1.2.0 # via stack-data fastjsonschema==2.18.0 # via nbformat -fonttools==4.42.0 +fonttools==4.42.1 # via matplotlib fqdn==1.5.1 # via jsonschema @@ -193,7 +193,7 @@ jupyter-events==0.7.0 # via jupyter-server jupyter-lsp==2.2.0 # via jupyterlab -jupyter-server==2.7.1 +jupyter-server==2.7.2 # via # jupyter-lsp # jupyterlab @@ -231,15 +231,11 @@ mccabe==0.7.0 # via pylint mistune==3.0.1 # via nbconvert -mypy==0.990 - # via -r hail/hail/python/dev/requirements.txt mypy-extensions==1.0.0 - # via - # black - # mypy + # via black nbclient==0.8.0 # via nbconvert -nbconvert==7.7.3 +nbconvert==7.7.4 # via # jupyter # jupyter-server @@ -256,6 +252,8 @@ nest-asyncio==1.5.7 # via # -c hail/hail/python/dev/../pinned-requirements.txt # ipykernel +nodeenv==1.8.0 + # via pyright notebook==7.0.2 # via jupyter notebook-shim==0.2.3 @@ -341,6 +339,8 @@ pylint==2.17.5 # via -r hail/hail/python/dev/requirements.txt pyparsing==3.0.9 # via matplotlib +pyright==1.1.324 + # via -r hail/hail/python/dev/requirements.txt pytest==7.4.0 # via # -r hail/hail/python/dev/requirements.txt @@ -417,7 +417,7 @@ rpds-py==0.9.2 # via # jsonschema # referencing -ruff==0.0.284 +ruff==0.0.285 # via -r hail/hail/python/dev/requirements.txt send2trash==1.8.2 # via jupyter-server @@ -444,7 +444,7 @@ sphinx==6.2.1 # sphinxcontrib-katex sphinx-autodoc-typehints==1.23.0 # via -r hail/hail/python/dev/requirements.txt -sphinx-rtd-theme==1.2.2 +sphinx-rtd-theme==1.3.0 # via -r hail/hail/python/dev/requirements.txt sphinxcontrib-applehelp==1.0.4 # via sphinx @@ -476,7 +476,6 @@ tomli==2.0.1 # via # black # jupyterlab - # mypy # pylint # pytest tomlkit==0.12.1 @@ -522,7 +521,7 @@ types-pyyaml==6.0.12.11 # via -r hail/hail/python/dev/requirements.txt types-requests==2.31.0.2 # via -r hail/hail/python/dev/requirements.txt -types-setuptools==68.0.0.3 +types-setuptools==68.1.0.0 # via -r hail/hail/python/dev/requirements.txt types-six==1.16.21.9 # via -r hail/hail/python/dev/requirements.txt @@ -539,7 +538,6 @@ typing-extensions==4.7.1 # async-lru # black # ipython - # mypy # pylint uri-template==1.3.0 # via jsonschema @@ -555,7 +553,7 @@ webencodings==0.5.1 # via # bleach # tinycss2 -websocket-client==1.6.1 +websocket-client==1.6.2 # via jupyter-server widgetsnbextension==4.0.8 # via ipywidgets @@ -567,3 +565,6 @@ zipp==3.16.2 # via # importlib-metadata # importlib-resources + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/hail/python/dev/requirements.txt b/hail/python/dev/requirements.txt index d962cf0726c..75b0f8f5c5f 100644 --- a/hail/python/dev/requirements.txt +++ b/hail/python/dev/requirements.txt @@ -1,6 +1,5 @@ -c ../pinned-requirements.txt -mypy==0.990 pylint>=2.13.5,<3 black>=22.8.0,<23 ruff>=0.0.264,<1 @@ -13,6 +12,7 @@ pytest-instafail>=0.4.2,<1 pytest-asyncio>=0.14.0,<1 pytest-timestamper>=0.0.9,<1 pytest-timeout>=2.1,<3 +pyright>=1.1.324<1.2 sphinx>=6,<7 sphinx-autodoc-typehints==1.23.0 nbsphinx>=0.8.8,<1 @@ -22,7 +22,7 @@ sphinxcontrib.katex>=0.9.0,<1 fswatch>=0.1.1,<1 matplotlib>=3.5,<4 -# mypy library stubs +# library type stubs types-Deprecated types-PyMySQL types-PyYAML diff --git a/hail/python/hail/__init__.py b/hail/python/hail/__init__.py index c82b6383cff..ba9c4696559 100644 --- a/hail/python/hail/__init__.py +++ b/hail/python/hail/__init__.py @@ -50,6 +50,7 @@ from . import ir # noqa: E402 from . import backend # noqa: E402 from . import nd # noqa: E402 +from . import utils # noqa: E402 from . import vds # noqa: E402 from .context import (init, init_local, init_batch, stop, spark_context, tmp_dir, # noqa: E402 @@ -113,6 +114,7 @@ 'citation', 'cite_hail', 'cite_hail_bibtex', + 'utils', 'version', 'ANY_REGION', ] diff --git a/hail/python/hailtop/aiocloud/aioaws/fs.py b/hail/python/hailtop/aiocloud/aioaws/fs.py index 3d8f063a747..6db1b402177 100644 --- a/hail/python/hailtop/aiocloud/aioaws/fs.py +++ b/hail/python/hailtop/aiocloud/aioaws/fs.py @@ -486,7 +486,7 @@ async def should_yield(entry: S3FileListEntry): return False return True - async def cons(first_entry, it): + async def cons(first_entry, it) -> AsyncIterator[FileListEntry]: if await should_yield(first_entry): yield first_entry try: diff --git a/hail/python/hailtop/aiocloud/aioazure/fs.py b/hail/python/hailtop/aiocloud/aioazure/fs.py index 2f4eb9ea8b9..5e61adeef20 100644 --- a/hail/python/hailtop/aiocloud/aioazure/fs.py +++ b/hail/python/hailtop/aiocloud/aioazure/fs.py @@ -387,9 +387,10 @@ async def generate_sas_token( permissions: str = "rw", valid_interval: timedelta = timedelta(hours=1) ) -> str: + assert self._credential mgmt_client = StorageManagementClient(self._credential, subscription_id) storage_keys = await mgmt_client.storage_accounts.list_keys(resource_group, account) - storage_key = storage_keys.keys[0].value + storage_key = storage_keys.keys[0].value # type: ignore token = generate_account_sas( account, @@ -584,7 +585,7 @@ async def should_yield(entry): return False return True - async def cons(first_entry, it): + async def cons(first_entry, it) -> AsyncIterator[FileListEntry]: if await should_yield(first_entry): yield first_entry try: diff --git a/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py b/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py index c9cc519fa87..358ddff71b2 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/client/storage_client.py @@ -624,11 +624,11 @@ def get_bucket_and_name(url: str) -> Tuple[str, str]: return (bucket, name) - async def open(self, url: str) -> ReadableStream: + async def open(self, url: str) -> GetObjectStream: bucket, name = self.get_bucket_and_name(url) return await self._storage_client.get_object(bucket, name) - async def _open_from(self, url: str, start: int, *, length: Optional[int] = None) -> ReadableStream: + async def _open_from(self, url: str, start: int, *, length: Optional[int] = None) -> GetObjectStream: bucket, name = self.get_bucket_and_name(url) range_str = f'bytes={start}-' if length is not None: @@ -734,7 +734,7 @@ async def should_yield(entry): return False return True - async def cons(first_entry, it): + async def cons(first_entry, it) -> AsyncIterator[FileListEntry]: if await should_yield(first_entry): yield first_entry try: diff --git a/hail/python/hailtop/aiocloud/aiogoogle/user_config.py b/hail/python/hailtop/aiocloud/aiogoogle/user_config.py index 53c4e832de3..cdcee03da77 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/user_config.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/user_config.py @@ -6,7 +6,8 @@ from dataclasses import dataclass -from hailtop.config.user_config import ConfigVariable, configuration_of +from hailtop.config.user_config import configuration_of +from hailtop.config.variables import ConfigVariable GCSRequesterPaysConfiguration = Union[str, Tuple[str, List[str]]] diff --git a/hail/python/hailtop/aiotools/fs/fs.py b/hail/python/hailtop/aiotools/fs/fs.py index 71e2efb5b98..a3472f5ee9c 100644 --- a/hail/python/hailtop/aiotools/fs/fs.py +++ b/hail/python/hailtop/aiotools/fs/fs.py @@ -1,5 +1,6 @@ from typing import (Any, AsyncContextManager, Optional, Type, Set, AsyncIterator, Callable, TypeVar, - Generic, List) + Generic, List, Awaitable, Union, Tuple) +from typing_extensions import ParamSpec from types import TracebackType import abc import asyncio @@ -9,6 +10,17 @@ from .exceptions import FileAndDirectoryError +T = TypeVar("T") +P = ParamSpec("P") + + +async def with_exception(f: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs) -> Union[Tuple[T, None], Tuple[None, Exception]]: + try: + return (await f(*args, **kwargs)), None + except Exception as e: + return None, e + + class FileStatus(abc.ABC): @abc.abstractmethod async def size(self) -> int: @@ -200,12 +212,6 @@ async def staturl(self, url: str) -> str: async def _staturl_parallel_isfile_isdir(self, url: str) -> str: assert not url.endswith('/') - async def with_exception(f, *args, **kwargs): - try: - return (await f(*args, **kwargs)), None - except Exception as e: - return None, e - [(is_file, isfile_exc), (is_dir, isdir_exc)] = await asyncio.gather( with_exception(self.isfile, url), with_exception(self.isdir, url + '/')) # raise exception deterministically diff --git a/hail/python/hailtop/aiotools/weighted_semaphore.py b/hail/python/hailtop/aiotools/weighted_semaphore.py index d899c0779dd..e910572af11 100644 --- a/hail/python/hailtop/aiotools/weighted_semaphore.py +++ b/hail/python/hailtop/aiotools/weighted_semaphore.py @@ -1,4 +1,4 @@ -from typing import Optional, Tuple, Type +from typing import Optional, Type from sortedcontainers import SortedKeyList from types import TracebackType import asyncio @@ -24,7 +24,7 @@ class WeightedSemaphore: def __init__(self, value: int): self.max = value self.value = value - self.events: SortedKeyList[Tuple[int, asyncio.Event]] = SortedKeyList(key=lambda x: x[0]) + self.events = SortedKeyList(key=lambda x: x[0]) def release(self, n: int) -> None: self.value += n diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index 334e4c1bad4..13d0111a0d7 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -528,7 +528,7 @@ def _run(self, disable_progress_bar: bool = False, callback: Optional[str] = None, token: Optional[str] = None, - **backend_kwargs) -> bc.Batch: # pylint: disable-msg=too-many-statements + **backend_kwargs) -> Optional[bc.Batch]: # pylint: disable-msg=too-many-statements """Execute a batch. Warning @@ -770,7 +770,6 @@ async def compile_job(job): parents=parents, attributes={'name': 'remove_tmpdir'}, always_run=True) - jobs_to_command[j] = cmd n_jobs_submitted += 1 if verbose: @@ -800,7 +799,7 @@ async def compile_job(job): if wait and len(unsubmitted_jobs) > 0: if verbose: print(f'Waiting for batch {batch_id}...') - starting_job_id = min(j._client_job.job_id for j in unsubmitted_jobs) + starting_job_id: int = min(j._client_job.job_id for j in unsubmitted_jobs) # type: ignore await asyncio.sleep(0.6) # it is not possible for the batch to be finished in less than 600ms status = await batch_handle._async_batch.wait(disable_progress_bar=disable_progress_bar, starting_job=starting_job_id) print(f'batch {batch_id} complete: {status["state"]}') diff --git a/hail/python/hailtop/batch/batch.py b/hail/python/hailtop/batch/batch.py index 8f5dba433b4..971a42d258f 100644 --- a/hail/python/hailtop/batch/batch.py +++ b/hail/python/hailtop/batch/batch.py @@ -1,7 +1,7 @@ import os import warnings import re -from typing import Callable, Optional, Dict, Union, List, Any, Set +from typing import Callable, Optional, Dict, Union, List, Any, Set, Literal, overload from io import BytesIO import dill @@ -643,11 +643,15 @@ def select_jobs(self, pattern: str) -> List[job.Job]: return [job for job in self._jobs if job.name is not None and re.match(pattern, job.name) is not None] + @overload + def run(self, dry_run: Literal[False] = ..., verbose: bool = ..., delete_scratch_on_exit: bool = ..., **backend_kwargs: Any) -> _bc.Batch: ... + @overload + def run(self, dry_run: Literal[True] = ..., verbose: bool = ..., delete_scratch_on_exit: bool = ..., **backend_kwargs: Any) -> None: ... def run(self, dry_run: bool = False, verbose: bool = False, delete_scratch_on_exit: bool = True, - **backend_kwargs: Any): + **backend_kwargs: Any) -> Optional[_bc.Batch]: """ Execute a batch. @@ -706,5 +710,6 @@ def schedule_job(j): self._DEPRECATED_fs = None return run_result + def __str__(self): return self._uid diff --git a/hail/python/hailtop/batch/batch_pool_executor.py b/hail/python/hailtop/batch/batch_pool_executor.py index ef2f30925c3..e9d720f957b 100644 --- a/hail/python/hailtop/batch/batch_pool_executor.py +++ b/hail/python/hailtop/batch/batch_pool_executor.py @@ -3,7 +3,7 @@ from io import BytesIO import warnings import asyncio -import concurrent +import concurrent.futures import dill import functools @@ -394,8 +394,7 @@ def run_async(*args, **kwargs): "''') output_gcs = self.outputs + f'{name}/output' batch.write_output(j.ofile, output_gcs) - backend_batch = batch.run(wait=False, - disable_progress_bar=True)._async_batch + backend_batch = batch.run(wait=False, disable_progress_bar=True)._async_batch try: return BatchPoolFuture(self, backend_batch, @@ -575,7 +574,7 @@ def exception(self, timeout: Optional[Union[float, int]] = None): raise concurrent.futures.CancelledError() self.result(timeout) - def add_done_callback(self, fn): + def add_done_callback(self, _): """NOT IMPLEMENTED """ raise NotImplementedError() diff --git a/hail/python/hailtop/batch/docs/conf.py b/hail/python/hailtop/batch/docs/conf.py index b5d4d94436f..e323ff78709 100644 --- a/hail/python/hailtop/batch/docs/conf.py +++ b/hail/python/hailtop/batch/docs/conf.py @@ -29,7 +29,7 @@ # The full version, including alpha/beta/rc tags release = '' nitpicky = True -nitpick_ignore = [('py:class', 'hailtop.batch_client.client.Batch')] +nitpick_ignore = [('py:class', 'hailtop.batch_client.client.Batch'), ('py:class', 'typing.Self')] # -- General configuration --------------------------------------------------- diff --git a/hail/python/hailtop/batch/job.py b/hail/python/hailtop/batch/job.py index ce5e914db47..9085ffe3fb8 100644 --- a/hail/python/hailtop/batch/job.py +++ b/hail/python/hailtop/batch/job.py @@ -6,6 +6,7 @@ import warnings from shlex import quote as shq from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union, cast +from typing_extensions import Self import hailtop.batch_client.client as bc @@ -132,7 +133,7 @@ def _add_internal_outputs(self, resource: '_resource.Resource') -> None: def _add_inputs(self, resource: '_resource.Resource') -> None: _add_resource_to_set(self._inputs, resource, include_rg=False) - def depends_on(self, *jobs: 'Job') -> 'Job': + def depends_on(self, *jobs: 'Job') -> Self: """ Explicitly set dependencies on other jobs. @@ -182,7 +183,7 @@ def depends_on(self, *jobs: 'Job') -> 'Job': def env(self, variable: str, value: str): self._env[variable] = value - def storage(self, storage: Optional[Union[str, int]]) -> 'Job': + def storage(self, storage: Optional[Union[str, int]]) -> Self: """ Set the job's storage size. @@ -231,7 +232,7 @@ def storage(self, storage: Optional[Union[str, int]]) -> 'Job': self._storage = opt_str(storage) return self - def memory(self, memory: Optional[Union[str, int]]) -> 'Job': + def memory(self, memory: Optional[Union[str, int]]) -> Self: """ Set the job's memory requirements. @@ -274,7 +275,7 @@ def memory(self, memory: Optional[Union[str, int]]) -> 'Job': self._memory = opt_str(memory) return self - def cpu(self, cores: Optional[Union[str, int, float]]) -> 'Job': + def cpu(self, cores: Optional[Union[str, int, float]]) -> Self: """ Set the job's CPU requirements. @@ -314,7 +315,7 @@ def cpu(self, cores: Optional[Union[str, int, float]]) -> 'Job': self._cpu = opt_str(cores) return self - def always_run(self, always_run: bool = True) -> 'Job': + def always_run(self, always_run: bool = True) -> Self: """ Set the job to always run, even if dependencies fail. @@ -342,7 +343,7 @@ def always_run(self, always_run: bool = True) -> 'Job': self._always_run = always_run return self - def spot(self, is_spot: bool) -> 'Job': + def spot(self, is_spot: bool) -> Self: """ Set whether a job is run on spot instances. By default, all jobs run on spot instances. @@ -368,7 +369,7 @@ def spot(self, is_spot: bool) -> 'Job': self._preemptible = is_spot return self - def regions(self, regions: Optional[List[str]]) -> 'Job': + def regions(self, regions: Optional[List[str]]) -> Self: """ Set the cloud regions a job can run in. @@ -415,7 +416,7 @@ def regions(self, regions: Optional[List[str]]) -> 'Job': self._regions = regions return self - def timeout(self, timeout: Optional[Union[float, int]]) -> 'Job': + def timeout(self, timeout: Optional[Union[float, int]]) -> Self: """ Set the maximum amount of time this job can run for in seconds. @@ -448,7 +449,7 @@ def timeout(self, timeout: Optional[Union[float, int]]) -> 'Job': self._timeout = timeout return self - def gcsfuse(self, bucket, mount_point, read_only=True): + def gcsfuse(self, bucket, mount_point, read_only=True) -> Self: """ Add a bucket to mount with gcsfuse. @@ -488,7 +489,7 @@ def gcsfuse(self, bucket, mount_point, read_only=True): warnings.warn("The 'gcsfuse' method has been deprecated. Use the 'cloudfuse' method instead.") return self.cloudfuse(bucket, mount_point, read_only=read_only) - def cloudfuse(self, bucket: str, mount_point: str, *, read_only: bool = True): + def cloudfuse(self, bucket: str, mount_point: str, *, read_only: bool = True) -> Self: """ Add a bucket to mount with gcsfuse in GCP or a storage container with blobfuse in Azure. @@ -547,7 +548,7 @@ def cloudfuse(self, bucket: str, mount_point: str, *, read_only: bool = True): self._cloudfuse.append((bucket, mount_point, read_only)) return self - def always_copy_output(self, always_copy_output: bool = True) -> 'Job': + def always_copy_output(self, always_copy_output: bool = True) -> Self: """ Set the job to always copy output to cloud storage, even if the job failed. diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index 9fcda0fc8f7..7cfe64c5890 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -1,4 +1,4 @@ -from typing import Optional, Dict, Any, List, Tuple, Union +from typing import AsyncIterator, Optional, Dict, Any, List, Tuple, Union import math import random import logging @@ -166,11 +166,11 @@ def _get_duration(container_status): return runtime.get('duration') - durations = [_get_duration(container_status) for task, container_status in container_statuses.items()] + durations = [_get_duration(container_status) for container_status in container_statuses.values()] if any(d is None for d in durations): return None - return sum(durations) + return sum(durations) # type: ignore @staticmethod def submitted_job(batch: 'Batch', job_id: int, _status: Optional[dict] = None): @@ -259,20 +259,21 @@ async def is_ready(self): # msec_mcpu: int # cost: float # } - async def status(self) -> dict: + async def status(self) -> Dict[str, Any]: self._raise_if_not_submitted() resp = await self._client._get(f'/api/v1alpha/batches/{self.batch_id}/jobs/{self.job_id}') self._status = await resp.json() assert self._status is not None return self._status - async def wait(self): + async def wait(self) -> Dict[str, Any]: return await self._wait_for_states(*complete_states) - async def _wait_for_states(self, *states: str): + async def _wait_for_states(self, *states: str) -> Dict[str, Any]: tries = 0 while True: if await self._is_job_in_state(states) or await self.is_complete(): + assert self._status return self._status tries += 1 await sleep_before_try(tries) @@ -355,7 +356,7 @@ async def cancel(self): self._raise_if_not_created() await self._client._patch(f'/api/v1alpha/batches/{self.id}/cancel') - async def jobs(self, q: Optional[str] = None, version: Optional[int] = None): + async def jobs(self, q: Optional[str] = None, version: Optional[int] = None) -> AsyncIterator[Dict[str, Any]]: self._raise_if_not_created() if version is None: version = 1 @@ -378,7 +379,7 @@ async def get_job(self, job_id: int) -> Job: self._raise_if_not_created() return await self._client.get_job(self.id, job_id) - async def get_job_log(self, job_id: int) -> Optional[Dict[str, Any]]: + async def get_job_log(self, job_id: int) -> Dict[str, Any]: self._raise_if_not_created() return await self._client.get_job_log(self.id, job_id) @@ -923,7 +924,7 @@ async def get_job(self, batch_id, job_id): j = await j_resp.json() return Job.submitted_job(b, j['job_id'], _status=j) - async def get_job_log(self, batch_id, job_id) -> Optional[Dict[str, Any]]: + async def get_job_log(self, batch_id, job_id) -> Dict[str, Any]: resp = await self._get(f'/api/v1alpha/batches/{batch_id}/jobs/{job_id}/log') return await resp.json() diff --git a/hail/python/hailtop/batch_client/client.py b/hail/python/hailtop/batch_client/client.py index 4ddcb051dd7..f6cf9f00749 100644 --- a/hail/python/hailtop/batch_client/client.py +++ b/hail/python/hailtop/batch_client/client.py @@ -163,7 +163,7 @@ def get_job(self, job_id: int) -> Job: j = async_to_blocking(self._async_batch.get_job(job_id)) return Job(j) - def get_job_log(self, job_id: int) -> Optional[Dict[str, Any]]: + def get_job_log(self, job_id: int) -> Dict[str, Any]: return async_to_blocking(self._async_batch.get_job_log(job_id)) def wait(self, *args, **kwargs): diff --git a/hail/python/hailtop/cleanup_gcr/__main__.py b/hail/python/hailtop/cleanup_gcr/__main__.py index bff7f7ada40..7cdc2890b79 100644 --- a/hail/python/hailtop/cleanup_gcr/__main__.py +++ b/hail/python/hailtop/cleanup_gcr/__main__.py @@ -1,5 +1,6 @@ import sys import time +from typing import Awaitable, List, TypeVar import logging import asyncio import aiohttp @@ -9,6 +10,9 @@ log = logging.getLogger(__name__) +T = TypeVar('T') + + class AsyncIOExecutor: def __init__(self, parallelism): self._semaphore = asyncio.Semaphore(parallelism) @@ -31,7 +35,7 @@ def submit(self, aw): self.task_manager.ensure_future(self._run(fut, aw)) return fut - async def gather(self, aws): + async def gather(self, aws: List[Awaitable[T]]) -> List[T]: futs = [self.submit(aw) for aw in aws] return [await fut for fut in futs] @@ -47,16 +51,14 @@ def shutdown(self): async def cleanup_digest(self, image, digest, tags): log.info(f'cleaning up digest {image}@{digest}') - async def delete_tag(tag): + async def delete_tag(tag: str): try: await self._client.delete(f'/{image}/manifests/{tag}') except aiohttp.ClientResponseError as e: if e.status != 404: raise - await self._executor.gather([ - delete_tag(tag) - for tag in tags]) + await self._executor.gather([delete_tag(tag) for tag in tags]) try: await self._executor.submit(self._client.delete(f'/{image}/manifests/{digest}')) diff --git a/hail/python/hailtop/fs/fs.py b/hail/python/hailtop/fs/fs.py index 46d3e7cf742..10fc452855d 100644 --- a/hail/python/hailtop/fs/fs.py +++ b/hail/python/hailtop/fs/fs.py @@ -1,13 +1,12 @@ import abc -import io -from typing import List +from typing import IO, List from .stat_result import StatResult class FS(abc.ABC): @abc.abstractmethod - def open(self, path: str, mode: str = 'r', buffer_size: int = 8192) -> io.IOBase: + def open(self, path: str, mode: str = 'r', buffer_size: int = 8192) -> IO: raise NotImplementedError @abc.abstractmethod diff --git a/hail/python/hailtop/hailctl/batch/batch_cli_utils.py b/hail/python/hailtop/hailctl/batch/batch_cli_utils.py index b30eb8c050d..d4d286d1420 100644 --- a/hail/python/hailtop/hailctl/batch/batch_cli_utils.py +++ b/hail/python/hailtop/hailctl/batch/batch_cli_utils.py @@ -2,13 +2,13 @@ from enum import Enum import yaml import csv -from typing import List, Dict, Callable, Annotated as Ann +from typing import Any, List, Dict, Callable, Annotated as Ann import tabulate import io from typer import Option as Opt -TableData = List[Dict[str, str]] +TableData = List[Dict[str, Any]] TABLE_FORMAT_OPTIONS = ['json', 'yaml', 'csv', *tabulate.tabulate_formats] diff --git a/hail/python/hailtop/hailctl/batch/cli.py b/hail/python/hailtop/hailctl/batch/cli.py index e33e4299367..09bd5a740b9 100644 --- a/hail/python/hailtop/hailctl/batch/cli.py +++ b/hail/python/hailtop/hailctl/batch/cli.py @@ -52,7 +52,7 @@ def get(batch_id: int, output: StructuredFormatOption = StructuredFormat.YAML): with BatchClient('') as client: batch = get_batch_if_exists(client, batch_id) if batch: - print(make_formatter(output)(batch.last_known_status())) + print(make_formatter(output)([batch.last_known_status()])) else: print(f"Batch with id {batch_id} not found") @@ -145,7 +145,8 @@ def job(batch_id: int, job_id: int, output: StructuredFormatOption = StructuredF job = get_job_if_exists(client, batch_id, job_id) if job is not None: - print(make_formatter(output)(job._status)) + assert job._status + print(make_formatter(output)([job._status])) else: print(f"Job with ID {job_id} on batch {batch_id} not found") diff --git a/hail/python/hailtop/hailctl/batch/initialize.py b/hail/python/hailtop/hailctl/batch/initialize.py index 8f22cdfffd9..baffe4a13b2 100644 --- a/hail/python/hailtop/hailctl/batch/initialize.py +++ b/hail/python/hailtop/hailctl/batch/initialize.py @@ -202,6 +202,7 @@ async def async_basic_initialize(verbose: bool = False): typer.secho(f'You are currently logged in to Hail at domain {domain}.') user_info = await async_get_userinfo() + assert user_info username = user_info['username'] hail_identity = user_info['hail_identity'] trial_bp_name = user_info['trial_bp_name'] diff --git a/hail/python/hailtop/hailctl/config/config_variables.py b/hail/python/hailtop/hailctl/config/config_variables.py index 8273f8b126a..e8941295749 100644 --- a/hail/python/hailtop/hailctl/config/config_variables.py +++ b/hail/python/hailtop/hailctl/config/config_variables.py @@ -11,7 +11,7 @@ def config_variables(): from hailtop.batch_client.parse import CPU_REGEXPAT, MEMORY_REGEXPAT # pylint: disable=import-outside-toplevel - from hailtop.fs.router_fs import RouterAsyncFS # pylint: disable=import-outside-toplevel + from hailtop.aiotools.router_fs import RouterAsyncFS # pylint: disable=import-outside-toplevel global _config_variables diff --git a/hail/python/hailtop/hailctl/describe.py b/hail/python/hailtop/hailctl/describe.py index a3555049ab5..59d2c15c252 100644 --- a/hail/python/hailtop/hailctl/describe.py +++ b/hail/python/hailtop/hailctl/describe.py @@ -1,6 +1,6 @@ import asyncio import orjson -from typing import List, Optional, Annotated as Ann +from typing import List, Optional, Union, Annotated as Ann from os import path from zlib import decompress, MAX_WBITS from statistics import median, mean, stdev @@ -71,7 +71,7 @@ def key_str(k): def get_partitions_info_str(j): - partitions = j['components']['partition_counts']['counts'] + partitions: List[Union[int, float]] = j['components']['partition_counts']['counts'] partitions_info = { 'Partitions': len(partitions), 'Rows': sum(partitions), diff --git a/hail/python/hailtop/httpx.py b/hail/python/hailtop/httpx.py index 8fff6623d5c..54330bf1e3e 100644 --- a/hail/python/hailtop/httpx.py +++ b/hail/python/hailtop/httpx.py @@ -3,6 +3,8 @@ from types import TracebackType import orjson import aiohttp +import aiohttp.abc +import aiohttp.typedefs from .utils import async_to_blocking from .tls import internal_client_ssl_context, external_client_ssl_context @@ -114,7 +116,7 @@ def __init__(self, ) def request( - self, method: str, url: aiohttp.client.StrOrURL, **kwargs: Any + self, method: str, url: aiohttp.typedefs.StrOrURL, **kwargs: Any ) -> aiohttp.client._RequestContextManager: raise_for_status = kwargs.pop('raise_for_status', self.raise_for_status) @@ -156,7 +158,7 @@ def ws_connect( return self.client_session.ws_connect(*args, **kwargs) def get( - self, url: aiohttp.client.StrOrURL, *, allow_redirects: bool = True, **kwargs: Any + self, url: aiohttp.typedefs.StrOrURL, *, allow_redirects: bool = True, **kwargs: Any ) -> aiohttp.client._RequestContextManager: return self.request('GET', url, allow_redirects=allow_redirects, **kwargs) @@ -173,17 +175,17 @@ async def get_read( return await resp.read() def options( - self, url: aiohttp.client.StrOrURL, *, allow_redirects: bool = True, **kwargs: Any + self, url: aiohttp.typedefs.StrOrURL, *, allow_redirects: bool = True, **kwargs: Any ) -> aiohttp.client._RequestContextManager: return self.request('OPTIONS', url, allow_redirects=allow_redirects, **kwargs) def head( - self, url: aiohttp.client.StrOrURL, *, allow_redirects: bool = False, **kwargs: Any + self, url: aiohttp.typedefs.StrOrURL, *, allow_redirects: bool = False, **kwargs: Any ) -> aiohttp.client._RequestContextManager: return self.request('HEAD', url, allow_redirects=allow_redirects, **kwargs) def post( - self, url: aiohttp.client.StrOrURL, *, data: Any = None, **kwargs: Any + self, url: aiohttp.typedefs.StrOrURL, *, data: Any = None, **kwargs: Any ) -> aiohttp.client._RequestContextManager: return self.request('POST', url, data=data, **kwargs) @@ -200,17 +202,17 @@ async def post_read( return await resp.read() def put( - self, url: aiohttp.client.StrOrURL, *, data: Any = None, **kwargs: Any + self, url: aiohttp.typedefs.StrOrURL, *, data: Any = None, **kwargs: Any ) -> aiohttp.client._RequestContextManager: return self.request('PUT', url, data=data, **kwargs) def patch( - self, url: aiohttp.client.StrOrURL, *, data: Any = None, **kwargs: Any + self, url: aiohttp.typedefs.StrOrURL, *, data: Any = None, **kwargs: Any ) -> aiohttp.client._RequestContextManager: return self.request('PATCH', url, data=data, **kwargs) def delete( - self, url: aiohttp.client.StrOrURL, **kwargs: Any + self, url: aiohttp.typedefs.StrOrURL, **kwargs: Any ) -> aiohttp.client._RequestContextManager: return self.request('DELETE', url, **kwargs) diff --git a/hail/python/hailtop/utils/__init__.py b/hail/python/hailtop/utils/__init__.py index 0b8807f2505..29a01a0cd55 100644 --- a/hail/python/hailtop/utils/__init__.py +++ b/hail/python/hailtop/utils/__init__.py @@ -3,7 +3,7 @@ time_ns) from .utils import (unzip, async_to_blocking, blocking_to_async, AsyncWorkerPool, bounded_gather, grouped, sync_sleep_before_try, sleep_before_try, is_transient_error, - collect_agen, retry_all_errors, retry_transient_errors, + collect_aiter, retry_all_errors, retry_transient_errors, retry_transient_errors_with_debug_string, retry_long_running, run_if_changed, run_if_changed_idempotent, LoggingTimer, WaitableSharedPool, RETRY_FUNCTION_SCRIPT, sync_retry_transient_errors, @@ -60,7 +60,7 @@ 'run_if_changed_idempotent', 'LoggingTimer', 'WaitableSharedPool', - 'collect_agen', + 'collect_aiter', 'RETRY_FUNCTION_SCRIPT', 'sync_retry_transient_errors', 'retry_response_returning_functions', @@ -77,7 +77,6 @@ 'external_requests_client_session', 'url_basename', 'url_join', - 'validate', 'url_scheme', 'url_and_params', 'serialization', diff --git a/hail/python/hailtop/utils/rich_progress_bar.py b/hail/python/hailtop/utils/rich_progress_bar.py index e102e7b6cca..081060747c3 100644 --- a/hail/python/hailtop/utils/rich_progress_bar.py +++ b/hail/python/hailtop/utils/rich_progress_bar.py @@ -146,7 +146,7 @@ def update(self, advance: Optional[int] = None, **kwargs): def is_notebook() -> bool: try: - from IPython import get_ipython # pylint: disable=import-error,import-outside-toplevel + from IPython.core.getipython import get_ipython # pylint: disable=import-error,import-outside-toplevel return get_ipython().__class__.__name__ == 'ZMQInteractiveShell' except (NameError, ModuleNotFoundError): return False diff --git a/hail/python/hailtop/utils/time.py b/hail/python/hailtop/utils/time.py index 8a1ca5b3118..1d778fcb5ae 100644 --- a/hail/python/hailtop/utils/time.py +++ b/hail/python/hailtop/utils/time.py @@ -1,4 +1,5 @@ import time +from typing import Optional, overload import datetime import dateutil.parser @@ -24,7 +25,11 @@ def humanize_timedelta_msecs(delta_msecs): return humanize.naturaldelta(datetime.timedelta(milliseconds=delta_msecs)) -def parse_timestamp_msecs(ts): +@overload +def parse_timestamp_msecs(ts: None) -> None: ... +@overload +def parse_timestamp_msecs(ts: str) -> int: ... +def parse_timestamp_msecs(ts: Optional[str]) -> Optional[int]: if ts is None: return ts - return dateutil.parser.isoparse(ts).timestamp() * 1000 + return int(dateutil.parser.isoparse(ts).timestamp() * 1000) diff --git a/hail/python/hailtop/utils/utils.py b/hail/python/hailtop/utils/utils.py index 57e78b7a35a..237e2244d01 100644 --- a/hail/python/hailtop/utils/utils.py +++ b/hail/python/hailtop/utils/utils.py @@ -1,8 +1,9 @@ from typing import (Any, Callable, TypeVar, Awaitable, Mapping, Optional, Type, List, Dict, Iterable, Tuple, - Generic, cast, AsyncIterator, Iterator) -from typing import Literal + Generic, cast, AsyncIterator, Iterator, Union) +from typing import Literal, Sequence +from typing_extensions import ParamSpec from types import TracebackType -import concurrent +import concurrent.futures import contextlib import subprocess import traceback @@ -14,8 +15,8 @@ import logging import asyncio import aiohttp -import urllib -import urllib3 +import urllib.parse +import urllib3.exceptions import secrets import socket import requests @@ -44,6 +45,7 @@ T = TypeVar('T') # pylint: disable=invalid-name U = TypeVar('U') # pylint: disable=invalid-name +P = ParamSpec("P") def unpack_comma_delimited_inputs(inputs: List[str]) -> List[str]: @@ -114,7 +116,7 @@ def grouped(n: int, ls: List[T]) -> Iterable[List[T]]: yield group -def partition(k: int, ls: List[T]) -> Iterable[List[T]]: +def partition(k: int, ls: Sequence[T]) -> Iterable[Sequence[T]]: if k == 0: assert not ls return [] @@ -193,7 +195,7 @@ def __init__(self, self._done = asyncio.Event() self._return_exceptions = return_exceptions - self._results: List[Optional[T]] = [None] * len(pfs) + self._results: List[Union[T, Exception, None]] = [None] * len(pfs) self._errors: List[BaseException] = [] self._workers = [] @@ -474,7 +476,7 @@ async def __aexit__(self, async def bounded_gather2_return_exceptions( sema: asyncio.Semaphore, *pfs: Callable[[], Awaitable[T]] -) -> List[T]: +) -> List[Union[Tuple[T, None], Tuple[None, Optional[BaseException]]]]: '''Run the partial functions `pfs` as tasks with parallelism bounded by `sema`, which should be `asyncio.Semaphore` whose initial value is the desired level of parallelism. @@ -484,7 +486,7 @@ async def bounded_gather2_return_exceptions( `(None, exc)` if the partial function raised the exception `exc`. ''' - async def run_with_sema_return_exceptions(pf): + async def run_with_sema_return_exceptions(pf: Callable[[], Awaitable[T]]): try: async with sema: return (await pf(), None) @@ -516,7 +518,7 @@ async def bounded_gather2_raise_exceptions( cancel_on_error is True, the unfinished tasks are all cancelled. ''' - async def run_with_sema(pf): + async def run_with_sema(pf: Callable[[], Awaitable[T]]): async with sema: return await pf() @@ -547,7 +549,7 @@ async def bounded_gather2( cancel_on_error: bool = False ) -> List[T]: if return_exceptions: - return await bounded_gather2_return_exceptions(sema, *pfs) + return await bounded_gather2_return_exceptions(sema, *pfs) # type: ignore return await bounded_gather2_raise_exceptions(sema, *pfs, cancel_on_error=cancel_on_error) @@ -673,7 +675,7 @@ def is_transient_error(e): return True if isinstance(e, asyncio.TimeoutError): return True - if (isinstance(e, aiohttp.client_exceptions.ClientConnectorError) + if (isinstance(e, aiohttp.ClientConnectorError) and hasattr(e, 'os_error') and is_transient_error(e.os_error)): return True @@ -783,7 +785,7 @@ async def _wrapper(f, *args, **kwargs): def retry_all_errors_n_times(max_errors=10, msg=None, error_logging_interval=10): - async def _wrapper(f, *args, **kwargs): + async def _wrapper(f: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs) -> T: tries = 0 while True: try: @@ -902,8 +904,8 @@ def init_poolmanager(self, connections, maxsize, block=False): timeout=self.timeout) -async def collect_agen(agen): - return [x async for x in agen] +async def collect_aiter(aiter: AsyncIterator[T]) -> List[T]: + return [x async for x in aiter] def dump_all_stacktraces(): @@ -912,7 +914,7 @@ def dump_all_stacktraces(): t.print_stack() -async def retry_long_running(name, f, *args, **kwargs): +async def retry_long_running(name: str, f: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs) -> T: delay_secs = 0.1 while True: start_time = time_msecs() diff --git a/hail/python/hailtop/utils/validate/validate.py b/hail/python/hailtop/utils/validate/validate.py index d75092648e0..a64e143fe24 100644 --- a/hail/python/hailtop/utils/validate/validate.py +++ b/hail/python/hailtop/utils/validate/validate.py @@ -1,4 +1,4 @@ -from typing import Union, Dict, Pattern, Callable, Any, List +from typing import Union, Dict, Pattern, Callable, Any, List, Optional import re import logging @@ -87,7 +87,7 @@ def validate(self, name: str, obj): class RegexValidator(TypedValidator): - def __init__(self, pattern: str, re_obj: Pattern, maxlen: int): + def __init__(self, pattern: str, re_obj: Optional[Pattern], maxlen: Optional[int]): super().__init__(str) self.pattern = pattern self.re_obj = re_obj if re_obj is not None else re.compile(pattern) diff --git a/hail/python/test/hail/utils/test_utils.py b/hail/python/test/hail/utils/test_utils.py index 61019be84f7..766208cf9c3 100644 --- a/hail/python/test/hail/utils/test_utils.py +++ b/hail/python/test/hail/utils/test_utils.py @@ -4,7 +4,7 @@ import hail as hl from hail.utils import * from hail.utils.misc import escape_str, escape_id -from hail.utils.java import Env, FatalError +from hail.utils.java import FatalError from hail.utils.linkedlist import LinkedList from ..helpers import * diff --git a/hail/python/test/hailtop/batch/test_batch.py b/hail/python/test/hailtop/batch/test_batch.py index 48b4769b701..e66228ddbd6 100644 --- a/hail/python/test/hailtop/batch/test_batch.py +++ b/hail/python/test/hailtop/batch/test_batch.py @@ -12,7 +12,8 @@ import re from hailtop import pip_version -from hailtop.batch import Batch, ServiceBackend, LocalBackend +from hailtop.batch import Batch, ServiceBackend, LocalBackend, ResourceGroup +from hailtop.batch.resource import JobResourceFile from hailtop.batch.exceptions import BatchException from hailtop.batch.globals import arg_max from hailtop.utils import grouped, async_to_blocking @@ -191,6 +192,7 @@ def test_declare_resource_group(self): b = self.batch() j = b.new_job() j.declare_resource_group(ofile={'log': "{root}.txt"}) + assert isinstance(j.ofile, ResourceGroup) j.command(f'echo "{msg}" > {j.ofile.log}') b.write_output(j.ofile.log, output_file.name) b.run() @@ -210,6 +212,7 @@ def test_resource_group_get_all_mentioned(self): b = self.batch() j = b.new_job() j.declare_resource_group(foo={'bed': '{root}.bed', 'bim': '{root}.bim'}) + assert isinstance(j.foo, ResourceGroup) j.command(f"cat {j.foo.bed}") assert j.foo.bed in j._mentioned assert j.foo.bim not in j._mentioned @@ -226,6 +229,7 @@ def test_resource_group_get_all_outputs(self): b = self.batch() j1 = b.new_job() j1.declare_resource_group(foo={'bed': '{root}.bed', 'bim': '{root}.bim'}) + assert isinstance(j1.foo, ResourceGroup) j1.command(f"cat {j1.foo.bed}") j2 = b.new_job() j2.command(f"cat {j1.foo.bed}") @@ -247,7 +251,7 @@ def test_multiple_isolated_jobs(self): output_files = [] try: - output_files = [tempfile.NamedTemporaryFile('w') for i in range(5)] + output_files = [tempfile.NamedTemporaryFile('w') for _ in range(5)] for i, ofile in enumerate(output_files): msg = f'hello world {i}' @@ -295,7 +299,7 @@ def test_scatter_gather(self): merger = b.new_job() merger.command('cat {files} > {ofile}'.format(files=' '.join([j.ofile for j in sorted(b.select_jobs('foo'), - key=lambda x: x.name, + key=lambda x: x.name, # type: ignore reverse=True)]), ofile=merger.ofile)) @@ -308,13 +312,16 @@ def test_add_extension_job_resource_file(self): b = self.batch() j = b.new_job() j.command(f'echo "hello" > {j.ofile}') + assert isinstance(j.ofile, JobResourceFile) j.ofile.add_extension('.txt.bgz') + assert j.ofile._value assert j.ofile._value.endswith('.txt.bgz') def test_add_extension_input_resource_file(self): input_file1 = '/tmp/data/example1.txt.bgz.foo' b = self.batch() in1 = b.read_input(input_file1) + assert in1._value assert in1._value.endswith('.txt.bgz.foo') def test_file_name_space(self): @@ -337,6 +344,7 @@ def test_resource_group_mentioned(self): b = self.batch() j = b.new_job() j.declare_resource_group(foo={'bed': '{root}.bed'}) + assert isinstance(j.foo, ResourceGroup) j.command(f'echo "hello" > {j.foo}') t2 = b.new_job() @@ -356,7 +364,7 @@ def test_envvar(self): def test_concatenate(self): b = self.batch() files = [] - for i in range(10): + for _ in range(10): j = b.new_job() j.command(f'touch {j.ofile}') files.append(j.ofile) @@ -395,7 +403,7 @@ def reformat(x, y): tail.command(f'cat {r3.as_str()} {r5.as_repr()} {r_mult.as_str()} {r_dict.as_json()} > {tail.ofile}') b.write_output(tail.ofile, output_file.name) - res = b.run() + b.run() assert self.read(output_file.name) == '3\n5\n30\n{\"x\": 3, \"y\": 5}' def test_backend_context_manager(self): @@ -488,14 +496,20 @@ def setUp(self): self.remote_tmpdir = remote_tmpdir + str(uuid.uuid4()) + '/' if remote_tmpdir.startswith('gs://'): - self.bucket = re.fullmatch('gs://(?P[^/]+).*', remote_tmpdir).groupdict()['bucket_name'] + match = re.fullmatch('gs://(?P[^/]+).*', remote_tmpdir) + assert match + self.bucket = match.groupdict()['bucket_name'] else: assert remote_tmpdir.startswith('hail-az://') if remote_tmpdir.startswith('hail-az://'): - storage_account, container_name = re.fullmatch('hail-az://(?P[^/]+)/(?P[^/]+).*', remote_tmpdir).groups() + match = re.fullmatch('hail-az://(?P[^/]+)/(?P[^/]+).*', remote_tmpdir) + assert match + storage_account, container_name = match.groups() else: assert remote_tmpdir.startswith('https://') - storage_account, container_name = re.fullmatch('https://(?P[^/]+).blob.core.windows.net/(?P[^/]+).*', remote_tmpdir).groups() + match = re.fullmatch('https://(?P[^/]+).blob.core.windows.net/(?P[^/]+).*', remote_tmpdir) + assert match + storage_account, container_name = match.groups() self.bucket = f'{storage_account}/{container_name}' self.cloud_input_dir = f'{self.remote_tmpdir}batch-tests/resources' @@ -584,6 +598,7 @@ def test_single_task_resource_group(self): b = self.batch() j = b.new_job() j.declare_resource_group(output={'foo': '{root}.foo'}) + assert isinstance(j.output, ResourceGroup) j.command(f'echo "hello" > {j.output.foo}') res = b.run() res_status = res.status() @@ -593,6 +608,7 @@ def test_single_task_write_resource_group(self): b = self.batch() j = b.new_job() j.declare_resource_group(output={'foo': '{root}.foo'}) + assert isinstance(j.output, ResourceGroup) j.command(f'echo "hello" > {j.output.foo}') b.write_output(j.output, f'{self.cloud_output_dir}/test_single_task_write_resource_group') b.write_output(j.output.foo, f'{self.cloud_output_dir}/test_single_task_write_resource_group_file.txt') @@ -644,7 +660,7 @@ def test_scatter_gather(self): merger = b.new_job() merger.command('cat {files} > {ofile}'.format(files=' '.join([j.ofile for j in sorted(b.select_jobs('foo'), - key=lambda x: x.name, + key=lambda x: x.name, # type: ignore reverse=True)]), ofile=merger.ofile)) @@ -664,7 +680,7 @@ def test_file_name_space(self): def test_local_paths_error(self): b = self.batch() - j = b.new_job() + b.new_job() for input in ["hi.txt", "~/hello.csv", "./hey.tsv", "/sup.json", "file://yo.yaml"]: with pytest.raises(ValueError) as e: b.read_input(input) @@ -813,7 +829,7 @@ def test_benchmark_lookalike_workflow(self): jobs.append(j) combine = b.new_job(f'combine_output').cpu(0.25) - for tasks in grouped(arg_max(), jobs): + for _ in grouped(arg_max(), jobs): combine.command(f'cat {" ".join(shq(j.ofile) for j in jobs)} >> {combine.ofile}') b.write_output(combine.ofile, f'{self.cloud_output_dir}/pipeline_benchmark_test.txt') # too slow @@ -906,6 +922,7 @@ def test_python_job_w_resource_group_unpack_individually(self): head = b.new_job() head.declare_resource_group(count={'r5': '{root}.r5', 'r3': '{root}.r3'}) + assert isinstance(head.count, ResourceGroup) head.command(f'echo "5" > {head.count.r5}') head.command(f'echo "3" > {head.count.r3}') @@ -952,6 +969,7 @@ def write(path): res = b.run() assert res + assert tail._job_id res_status = res.status() assert res_status['state'] == 'success', str((res_status, res.debug_info())) assert res.get_job_log(tail._job_id)['main'] == 'foo', str(res.debug_info()) @@ -961,6 +979,7 @@ def test_python_job_w_resource_group_unpack_jointly(self): head = b.new_job() head.declare_resource_group(count={'r5': '{root}.r5', 'r3': '{root}.r3'}) + assert isinstance(head.count, ResourceGroup) head.command(f'echo "5" > {head.count.r5}') head.command(f'echo "3" > {head.count.r3}') @@ -1074,7 +1093,7 @@ def test_big_batch_which_uses_slow_path(self): backend = ServiceBackend(remote_tmpdir=f'{self.remote_tmpdir}/temporary-files') b = Batch(backend=backend) # 8 * 256 * 1024 = 2 MiB > 1 MiB max bunch size - for i in range(8): + for _ in range(8): j1 = b.new_job() long_str = secrets.token_urlsafe(256 * 1024) j1.command(f'echo "{long_str}" > /dev/null') @@ -1265,7 +1284,7 @@ def test_update_batch_from_batch_id(self): res_status = res.status() assert res_status['state'] == 'success', str((res_status, res.debug_info())) - b2 = Batch.from_batch_id(b._batch_handle.id, backend=b._backend) + b2 = Batch.from_batch_id(res.id, backend=b._backend) j2 = b2.new_job() j2.command('true') res = b2.run() @@ -1289,6 +1308,7 @@ def write(paths): res = b.run() assert res + assert tail._job_id res_status = res.status() assert res_status['state'] == 'success', str((res_status, res.debug_info())) assert res.get_job_log(tail._job_id)['main'] == '01', str(res.debug_info()) @@ -1310,6 +1330,7 @@ def write(kwargs): res = b.run() assert res + assert tail._job_id res_status = res.status() assert res_status['state'] == 'success', str((res_status, res.debug_info())) assert res.get_job_log(tail._job_id)['main'] == 'ab', str(res.debug_info()) diff --git a/hail/python/test/hailtop/batch/test_batch_pool_executor.py b/hail/python/test/hailtop/batch/test_batch_pool_executor.py index 825f35d88b2..97d4f6a0364 100644 --- a/hail/python/test/hailtop/batch/test_batch_pool_executor.py +++ b/hail/python/test/hailtop/batch/test_batch_pool_executor.py @@ -17,6 +17,7 @@ class RecordingServiceBackend(ServiceBackend): def _run(self, *args, **kwargs): b = super()._run(*args, **kwargs) + assert b submitted_batch_ids.append(b.id) return b @@ -118,7 +119,7 @@ def test_map_chunksize(backend): for row in range(5) for x in [row, row, row, row, row]] col_args = [x - for row in range(5) + for _ in range(5) for x in list(range(5))] with BatchPoolExecutor(backend=backend, project='hail-vdc', image=PYTHON_DILL_IMAGE) as bpe: multiplication_table = list(bpe.map(lambda x, y: x * y, diff --git a/hail/python/test/hailtop/inter_cloud/test_copy.py b/hail/python/test/hailtop/inter_cloud/test_copy.py index bbf7ee39c42..de4c4f8acfa 100644 --- a/hail/python/test/hailtop/inter_cloud/test_copy.py +++ b/hail/python/test/hailtop/inter_cloud/test_copy.py @@ -1,4 +1,4 @@ -from typing import Tuple, Dict, AsyncIterator +from typing import Tuple, Dict, AsyncIterator, List import os import secrets from concurrent.futures import ThreadPoolExecutor @@ -6,7 +6,7 @@ import functools import pytest from hailtop.utils import url_scheme, bounded_gather2 -from hailtop.aiotools import LocalAsyncFS, Transfer, FileAndDirectoryError, Copier, AsyncFS +from hailtop.aiotools import LocalAsyncFS, Transfer, FileAndDirectoryError, Copier, AsyncFS, FileListEntry from hailtop.aiotools.router_fs import RouterAsyncFS from hailtop.aiocloud.aiogoogle import GoogleStorageAsyncFS from hailtop.aiocloud.aioaws import S3AsyncFS @@ -126,7 +126,7 @@ async def test_copy_behavior(copy_test_context, test_spec): dest_scheme = url_scheme(dest_base) if ((dest_scheme == 'gs' or dest_scheme == 's3' or dest_scheme == 'https') - and 'files' in result + and (result is not None and 'files' in result) and expected.get('exception') in ('IsADirectoryError', 'NotADirectoryError')): return @@ -457,7 +457,7 @@ async def write_file(fs, url, data): await f.write(data) -async def collect_files(it): +async def collect_files(it: AsyncIterator[FileListEntry]) -> List[str]: return [await x.url() async for x in it] @@ -500,7 +500,7 @@ async def test_file_and_directory_error_with_slash_empty_file(router_filesystem: @pytest.mark.asyncio async def test_file_and_directory_error_with_slash_non_empty_file_for_google_non_recursive(router_filesystem: Tuple[asyncio.Semaphore, AsyncFS, Dict[str, str]]): - sema, fs, bases = router_filesystem + _, fs, bases = router_filesystem src_base = await fresh_dir(fs, bases, 'gs') @@ -596,7 +596,7 @@ async def test_file_and_directory_error_with_slash_empty_file_only(router_filesy @pytest.mark.asyncio async def test_file_and_directory_error_with_slash_non_empty_file_only_google_non_recursive(router_filesystem: Tuple[asyncio.Semaphore, AsyncFS, Dict[str, str]]): - sema, fs, bases = router_filesystem + _, fs, bases = router_filesystem src_base = await fresh_dir(fs, bases, 'gs') diff --git a/hail/python/test/hailtop/inter_cloud/test_fs.py b/hail/python/test/hailtop/inter_cloud/test_fs.py index c67aeea3a0b..3bb5643776c 100644 --- a/hail/python/test/hailtop/inter_cloud/test_fs.py +++ b/hail/python/test/hailtop/inter_cloud/test_fs.py @@ -17,7 +17,7 @@ @pytest.fixture(params=['file', 'gs', 's3', 'azure-https', 'router/file', 'router/gs', 'router/s3', 'router/azure-https', 'sas/azure-https']) -async def filesystem(request) -> AsyncIterator[Tuple[asyncio.Semaphore, AsyncFS, str]]: +async def filesystem(request) -> AsyncIterator[Tuple[asyncio.Semaphore, AsyncFS, AsyncFSURL]]: token = secret_alnum_string() with ThreadPoolExecutor() as thread_pool: @@ -55,6 +55,7 @@ async def filesystem(request) -> AsyncIterator[Tuple[asyncio.Semaphore, AsyncFS, if request.param.startswith('sas'): sub_id = os.environ['HAIL_TEST_AZURE_SUBID'] res_grp = os.environ['HAIL_TEST_AZURE_RESGRP'] + assert isinstance(fs, AzureAsyncFS) sas_token = await fs.generate_sas_token(sub_id, res_grp, account, "rwdlc") base = fs.parse_url(f'https://{account}.blob.core.windows.net/{container}/tmp/{token}/?{sas_token}') else: diff --git a/hail/python/test/hailtop/test_aiogoogle.py b/hail/python/test/hailtop/test_aiogoogle.py index 066deeb9b9b..c493612da5f 100644 --- a/hail/python/test/hailtop/test_aiogoogle.py +++ b/hail/python/test/hailtop/test_aiogoogle.py @@ -3,7 +3,7 @@ from concurrent.futures import ThreadPoolExecutor import asyncio import pytest -import concurrent +import concurrent.futures import functools from hailtop.utils import secret_alnum_string, bounded_gather2, retry_transient_errors from hailtop.aiotools import LocalAsyncFS @@ -75,7 +75,7 @@ async def upload(): await f.write(b'foo') await retry_transient_errors(upload) async with await client.get_object(bucket, file) as f: - headers = f.headers() + headers = f.headers() # type: ignore assert 'ETag' in headers assert headers['X-Goog-Hash'] == 'crc32c=z8SuHQ==,md5=rL0Y20zC+Fzt72VPzMSk2A==' assert await f.read() == b'foo' diff --git a/hail/python/test/hailtop/utils/test_utils.py b/hail/python/test/hailtop/utils/test_utils.py index 9e93037c27a..809a6f219dd 100644 --- a/hail/python/test/hailtop/utils/test_utils.py +++ b/hail/python/test/hailtop/utils/test_utils.py @@ -191,7 +191,7 @@ def test_unzip(): assert unzip([(123, 456), ('abc', 'def')]) == ([123, 'abc'], [456, 'def']) assert unzip([(123, 'abc'), (456, 'def'), (789, 'ghi')]) == ([123, 456, 789], ['abc', 'def', 'ghi']) - + def test_digits_needed(): assert digits_needed(0) == 1 assert digits_needed(1) == 1 diff --git a/hail/scripts/assert_pypi_has_room.py b/hail/scripts/assert_pypi_has_room.py index edf50539a9c..d4eac55f971 100644 --- a/hail/scripts/assert_pypi_has_room.py +++ b/hail/scripts/assert_pypi_has_room.py @@ -1,4 +1,5 @@ import os +import sys wheel_size = os.path.getsize(os.environ["WHEEL"]) pypi_used_storage = int(os.environ["PYPI_USED_STORAGE"]) @@ -7,5 +8,5 @@ if wheel_size + pypi_used_storage > 10 * 1024 * 1024 * 1024: print('Insufficient space available at PyPI.') - exit(1) + sys.exit(1) print('Sufficient space is available at PyPI.') diff --git a/hail/scripts/test_requester_pays_parsing.py b/hail/scripts/test_requester_pays_parsing.py index d4d11e7699e..d73f09b30dc 100644 --- a/hail/scripts/test_requester_pays_parsing.py +++ b/hail/scripts/test_requester_pays_parsing.py @@ -1,12 +1,12 @@ -import pytest -import sys import os +import sys + +import pytest from hailtop.aiocloud.aiogoogle import get_gcs_requester_pays_configuration -from hailtop.aiocloud.aiogoogle.user_config import spark_conf_path, get_spark_conf_gcs_requester_pays_configuration -from hailtop.utils.process import CalledProcessError, check_exec_output +from hailtop.aiocloud.aiogoogle.user_config import get_spark_conf_gcs_requester_pays_configuration, spark_conf_path from hailtop.config.user_config import ConfigVariable, configuration_of - +from hailtop.utils.process import check_exec_output if 'YOU_MAY_OVERWRITE_MY_SPARK_DEFAULTS_CONF_AND_HAILCTL_SETTINGS' not in os.environ: print('This script will overwrite your spark-defaults.conf and hailctl settings. It is intended to be executed inside a container.') @@ -14,6 +14,7 @@ SPARK_CONF_PATH = spark_conf_path() +assert SPARK_CONF_PATH async def unset_hailctl(): @@ -34,7 +35,7 @@ async def unset_hailctl(): @pytest.mark.asyncio async def test_no_configuration(): - with open(SPARK_CONF_PATH, 'w') as f: + with open(SPARK_CONF_PATH, 'w'): pass await unset_hailctl() diff --git a/monitoring/monitoring/monitoring.py b/monitoring/monitoring/monitoring.py index c69affcb67d..1442dc4199b 100644 --- a/monitoring/monitoring/monitoring.py +++ b/monitoring/monitoring/monitoring.py @@ -5,7 +5,7 @@ import logging import os from collections import defaultdict, namedtuple -from typing import Dict +from typing import Any, Dict, List import aiohttp_session import prometheus_client as pc # type: ignore @@ -65,10 +65,10 @@ def get_last_day_month(dt): return datetime.datetime(dt.year, dt.month, last_day) -def format_data(records): +def format_data(records: List[Dict[str, Any]]): cost_by_service: Dict[str, int] = defaultdict(int) compute_cost_breakdown: Dict[str, int] = defaultdict(int) - cost_by_sku_source = [] + cost_by_sku_source: List[Dict[str, Any]] = [] for record in records: cost_by_sku_source.append(record) @@ -106,7 +106,7 @@ def non_optional_cost_str(cost: int): return (str_cost_by_service, str_compute_cost_breakdown, cost_by_sku_source) -async def _billing(request): +async def _billing(request: web.Request): app = request.app date_format = '%m/%Y' @@ -136,7 +136,7 @@ async def _billing(request): @routes.get('/api/v1alpha/billing') @auth.rest_authenticated_developers_only -async def get_billing(request: web.Request, userdata) -> web.Response: # pylint: disable=unused-argument +async def get_billing(request: web.Request, _) -> web.Response: cost_by_service, compute_cost_breakdown, cost_by_sku_label, time_period_query = await _billing(request) resp = { 'cost_by_service': cost_by_service, diff --git a/pyproject.toml b/pyproject.toml index c2f4ece0a93..e1005150311 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,3 +42,20 @@ known-first-party = ["auth", "batch", "ci", "gear", "hailtop", "monitoring", "we [pytest] timeout = 120 + +[tool.pyright] +ignore = [ + "**/sql", + "**/build", + "**/target", + "hail/python/hail", + "hail/python/test/hail", + "hail/python/hailtop/batch/docs", + "notebook", + "query", + "datasets", + "benchmark", + "docker/vep/vep.py", + "devbin", + "hail/src/test/resources/makeTestInfoScore.py", +] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 08d2eb7018a..00000000000 --- a/setup.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[mypy] -ignore_missing_imports = True -exclude = (hailtop/batch/docs|sql) -check_untyped_defs = True diff --git a/website/website/website.py b/website/website/website.py index 1c872967214..d95320f0759 100644 --- a/website/website/website.py +++ b/website/website/website.py @@ -3,6 +3,7 @@ from typing import Set import aiohttp_session +import aiohttp_session.cookie_storage import jinja2 from aiohttp import web from prometheus_async.aio.web import server_stats # type: ignore @@ -23,19 +24,19 @@ def redirect(from_url, to_url): - async def serve(request): # pylint: disable=unused-argument + async def serve(_): raise web.HTTPFound(to_url) routes.get(from_url)(serve) @routes.get('/healthcheck') -async def get_healthcheck(request): # pylint: disable=unused-argument +async def get_healthcheck(_): return web.Response() @routes.get('/robots.txt') -async def get_robots(request): # pylint: disable=unused-argument +async def get_robots(_): return web.Response(text='user-agent: *\nAllow: /') From 0132c1993e2b328fcf7d855e4bb9d8abbfeeb365 Mon Sep 17 00:00:00 2001 From: jigold Date: Tue, 29 Aug 2023 12:57:03 -0400 Subject: [PATCH 155/180] [devbin] Generate cleanup policies for GCP artifact registry (#13489) Fixes #13441 Usage: `python3 devbin/generate_gcp_ar_cleanup_policy.py > my_policy_file.txt` Reference: https://cloud.google.com/artifact-registry/docs/repositories/cleanup-policy Note, we have a maximum of 10 policies available. --- build.yaml | 27 ++++ devbin/generate_gcp_ar_cleanup_policy.py | 149 ++++++++++++++++++++++ docker/third-party/images.txt | 1 - infra/gcp-broad/gcp-ar-cleanup-policy.txt | 139 ++++++++++++++++++++ 4 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 devbin/generate_gcp_ar_cleanup_policy.py create mode 100644 infra/gcp-broad/gcp-ar-cleanup-policy.txt diff --git a/build.yaml b/build.yaml index f935809d99e..fd48841fa15 100644 --- a/build.yaml +++ b/build.yaml @@ -3829,3 +3829,30 @@ steps: - default_ns scopes: - deploy + - kind: runImage + name: test_gcp_ar_cleanup_policies + resources: + memory: standard + cpu: '0.25' + image: + valueFrom: ci_utils_image.image + script: | + set -ex + cd /io/repo/ + python3 devbin/generate_gcp_ar_cleanup_policy.py | diff - infra/gcp-broad/gcp-ar-cleanup-policy.txt + inputs: + - from: /repo/build.yaml + to: /io/repo/build.yaml + - from: /repo/devbin + to: /io/repo/devbin + - from: /repo/infra + to: /io/repo/infra + - from: /repo/docker + to: /io/repo/docker + - from: /repo/ci/test/resources + to: /io/repo/ci/test/resources + clouds: + - gcp + dependsOn: + - ci_utils_image + - default_ns diff --git a/devbin/generate_gcp_ar_cleanup_policy.py b/devbin/generate_gcp_ar_cleanup_policy.py new file mode 100644 index 00000000000..f8dcc4f1591 --- /dev/null +++ b/devbin/generate_gcp_ar_cleanup_policy.py @@ -0,0 +1,149 @@ +import abc +import json +import yaml + +from typing import List, Optional + + +class CleanupPolicy(abc.ABC): + @abc.abstractmethod + def to_dict(self): + pass + + +class DeletePolicy(CleanupPolicy): + def __init__(self, + name: str, + tag_state: str, + *, + tag_prefixes: Optional[List[str]] = None, + version_name_prefixes: Optional[List[str]] = None, + package_name_prefixes: Optional[List[str]] = None, + older_than: Optional[str] = None, + newer_than: Optional[str] = None): + self.name = name + self.tag_state = tag_state + self.tag_prefixes = tag_prefixes + self.version_name_prefixes = version_name_prefixes + self.package_name_prefixes = package_name_prefixes + self.older_than = older_than + self.newer_than = newer_than + + def to_dict(self): + data = {'name': self.name, 'action': {'type': 'Delete'}, 'condition': {'tagState': self.tag_state}} + condition = data['condition'] + if self.tag_prefixes is not None: + condition['tagPrefixes'] = self.tag_prefixes + if self.version_name_prefixes is not None: + condition['versionNamePrefixes'] = self.version_name_prefixes + if self.package_name_prefixes is not None: + condition['packageNamePrefixes'] = self.package_name_prefixes + if self.older_than: + condition['olderThan'] = self.older_than + if self.newer_than: + condition['newerThan'] = self.newer_than + return data + + +class ConditionalKeepPolicy(CleanupPolicy): + def __init__(self, + name: str, + tag_state: str, + *, + tag_prefixes: Optional[List[str]] = None, + version_name_prefixes: Optional[List[str]] = None, + package_name_prefixes: Optional[List[str]] = None, + older_than: Optional[str] = None, + newer_than: Optional[str] = None): + self.name = name + self.tag_state = tag_state + self.tag_prefixes = tag_prefixes + self.version_name_prefixes = version_name_prefixes + self.package_name_prefixes = package_name_prefixes + self.older_than = older_than + self.newer_than = newer_than + + def to_dict(self): + data = {'name': self.name, 'action': {'type': 'Keep'}, 'condition': {'tagState': self.tag_state}} + condition = data['condition'] + if self.tag_prefixes is not None: + condition['tagPrefixes'] = self.tag_prefixes + if self.version_name_prefixes is not None: + condition['versionNamePrefixes'] = self.version_name_prefixes + if self.package_name_prefixes is not None: + condition['packageNamePrefixes'] = self.package_name_prefixes + if self.older_than: + condition['olderThan'] = self.older_than + if self.newer_than: + condition['newerThan'] = self.newer_than + return data + + +class MostRecentVersionKeepPolicy(CleanupPolicy): + def __init__(self, + name: str, + package_name_prefixes: List[str], + keep_count: int): + self.name = name + self.package_name_prefixes = package_name_prefixes + self.keep_count = keep_count + + def to_dict(self): + data = { + 'name': self.name, + 'action': {'type': 'Keep'}, + 'mostRecentVersions': { + 'packageNamePrefixes': self.package_name_prefixes, + 'keepCount': self.keep_count + } + } + return data + + +third_party_images_fp = 'docker/third-party/images.txt' +third_party_packages = [] +with open(third_party_images_fp, 'r') as f: + for image in f: + image = image.strip() + package, _ = image.split(':') + if package not in third_party_packages: + third_party_packages.append(package) + +deploy_packages = [] + + +def scrape_build_yaml(file_path: str): + found_packages = [] + with open(file_path, 'r') as f: + config_str = f.read().strip() + build_config = yaml.safe_load(config_str) + for step in build_config['steps']: + if step['kind'] == 'buildImage2': + image = step['publishAs'] + if image not in found_packages: + found_packages.append(image) + return found_packages + + +deploy_packages.extend(scrape_build_yaml('build.yaml')) +deploy_packages.extend(scrape_build_yaml('ci/test/resources/build.yaml')) + +deploy_packages = list(set(deploy_packages)) + +third_party_packages.sort() +deploy_packages.sort() + +policies = [ + DeletePolicy('delete_untagged', 'untagged'), + DeletePolicy('delete_dev', 'tagged', tag_prefixes=['dev-'], older_than='3d'), + DeletePolicy('delete_test_pr', 'tagged', tag_prefixes=['test-pr-'], older_than='3d'), + DeletePolicy('delete_test_deploy', 'tagged', tag_prefixes=['test-deploy-'], older_than='3d'), + DeletePolicy('delete_pr_cache', 'tagged', tag_prefixes=['cache-pr-'], older_than='7d'), + DeletePolicy('delete_cache', 'tagged', tag_prefixes=['cache-'], older_than='30d'), + ConditionalKeepPolicy('keep_third_party', 'any', package_name_prefixes=third_party_packages), + MostRecentVersionKeepPolicy('keep_most_recent_deploy', package_name_prefixes=deploy_packages, keep_count=10), +] + +policies = [p.to_dict() for p in policies] + +print(json.dumps(policies, indent=4)) diff --git a/docker/third-party/images.txt b/docker/third-party/images.txt index fab1ad7f6c7..1f1dfdbf40c 100644 --- a/docker/third-party/images.txt +++ b/docker/third-party/images.txt @@ -4,7 +4,6 @@ envoyproxy/envoy:v1.22.3 ghost:3.0-alpine google/cloud-sdk:305.0.0-slim grafana/grafana:9.1.4 -jupyter/scipy-notebook jupyter/scipy-notebook:c094bb7219f9 moby/buildkit:v0.8.3-rootless python:3.9 diff --git a/infra/gcp-broad/gcp-ar-cleanup-policy.txt b/infra/gcp-broad/gcp-ar-cleanup-policy.txt new file mode 100644 index 00000000000..7c641d104ff --- /dev/null +++ b/infra/gcp-broad/gcp-ar-cleanup-policy.txt @@ -0,0 +1,139 @@ +[ + { + "name": "delete_untagged", + "action": { + "type": "Delete" + }, + "condition": { + "tagState": "untagged" + } + }, + { + "name": "delete_dev", + "action": { + "type": "Delete" + }, + "condition": { + "tagState": "tagged", + "tagPrefixes": [ + "dev-" + ], + "olderThan": "3d" + } + }, + { + "name": "delete_test_pr", + "action": { + "type": "Delete" + }, + "condition": { + "tagState": "tagged", + "tagPrefixes": [ + "test-pr-" + ], + "olderThan": "3d" + } + }, + { + "name": "delete_test_deploy", + "action": { + "type": "Delete" + }, + "condition": { + "tagState": "tagged", + "tagPrefixes": [ + "test-deploy-" + ], + "olderThan": "3d" + } + }, + { + "name": "delete_pr_cache", + "action": { + "type": "Delete" + }, + "condition": { + "tagState": "tagged", + "tagPrefixes": [ + "cache-pr-" + ], + "olderThan": "7d" + } + }, + { + "name": "delete_cache", + "action": { + "type": "Delete" + }, + "condition": { + "tagState": "tagged", + "tagPrefixes": [ + "cache-" + ], + "olderThan": "30d" + } + }, + { + "name": "keep_third_party", + "action": { + "type": "Keep" + }, + "condition": { + "tagState": "any", + "packageNamePrefixes": [ + "alpine", + "debian", + "envoyproxy/envoy", + "ghost", + "google/cloud-sdk", + "grafana/grafana", + "jupyter/scipy-notebook", + "moby/buildkit", + "python", + "redis", + "ubuntu" + ] + } + }, + { + "name": "keep_most_recent_deploy", + "action": { + "type": "Keep" + }, + "mostRecentVersions": { + "packageNamePrefixes": [ + "admin-pod", + "auth", + "base", + "batch", + "batch-worker", + "blog_nginx", + "ci", + "ci-hello", + "ci-utils", + "create_certs_image", + "curl", + "git-make-bash", + "hail-buildkit", + "hail-dev", + "hail-run", + "hail-ubuntu", + "hailgenetics/hail", + "hailgenetics/hailtop", + "hailgenetics/vep-grch37-85", + "linting", + "monitoring", + "netcat", + "notebook", + "notebook_nginx", + "query-build", + "test-ci-utils", + "test_hello_create_certs_image", + "volume", + "website", + "workdir" + ], + "keepCount": 10 + } + } +] From 0a2816f7695c3bb4de2b3314cf6efbcebf94fda0 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 30 Aug 2023 14:20:14 -0400 Subject: [PATCH 156/180] [ci] Add instruction for regenerating AR policy file (#13522) --- build.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/build.yaml b/build.yaml index fd48841fa15..8fdd351e6d2 100644 --- a/build.yaml +++ b/build.yaml @@ -3839,7 +3839,16 @@ steps: script: | set -ex cd /io/repo/ - python3 devbin/generate_gcp_ar_cleanup_policy.py | diff - infra/gcp-broad/gcp-ar-cleanup-policy.txt + new_policy=$(mktemp) + python3 devbin/generate_gcp_ar_cleanup_policy.py > $new_policy + diff $new_policy infra/gcp-broad/gcp-ar-cleanup-policy.txt || { + echo '>>> AR cleanup policy has changed, new policy is <<<' + cat $new_policy + echo '--------------------------------------' + echo "Please regenerate the policy file by running:" + echo "> python3 devbin/generate_gcp_ar_cleanup_policy.py > infra/gcp-broad/gcp-ar-cleanup-policy.txt" + exit 1 + } inputs: - from: /repo/build.yaml to: /io/repo/build.yaml From f658a92ca0fabc405744a891a97e540f63714524 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 30 Aug 2023 16:01:47 -0400 Subject: [PATCH 157/180] [batch] Dont treat unknown in DockerError 500s as transient (#13521) --- build.yaml | 2 +- hail/python/hailtop/utils/utils.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.yaml b/build.yaml index 8fdd351e6d2..f3053650fd7 100644 --- a/build.yaml +++ b/build.yaml @@ -3343,7 +3343,7 @@ steps: - gcp - kind: runImage name: mirror_hailgenetics_images - image: quay.io/skopeo/stable:v1.11.2 + image: quay.io/skopeo/stable:v1.13.2 script: | set -ex diff --git a/hail/python/hailtop/utils/utils.py b/hail/python/hailtop/utils/utils.py index 237e2244d01..386f26eaa40 100644 --- a/hail/python/hailtop/utils/utils.py +++ b/hail/python/hailtop/utils/utils.py @@ -713,7 +713,8 @@ def is_transient_error(e): if e.status == 500 and 'denied: retrieving permissions failed' in e.message: return False # DockerError(500, "Head https://gcr.io/v2/genomics-tools/samtools/manifests/latest: unknown: Project 'project:genomics-tools' not found or deleted.") - if e.status == 500 and 'not found or deleted' in e.message: + # DockerError(500, 'unknown: Tag v1.11.2 was deleted or has expired. To pull, revive via time machine') + if e.status == 500 and 'unknown' in e.message: return False return e.status in RETRYABLE_HTTP_STATUS_CODES if isinstance(e, TransientError): From b5e0c3cf542dbba257d672c912d4a239ffec1a72 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 30 Aug 2023 17:17:49 -0400 Subject: [PATCH 158/180] [ci] Use skopeo 1.13.2 (#13527) --- build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.yaml b/build.yaml index f3053650fd7..dc450e0d20a 100644 --- a/build.yaml +++ b/build.yaml @@ -66,7 +66,7 @@ steps: - azure - kind: runImage name: copy_third_party_images - image: quay.io/skopeo/stable:v1.11.2 + image: quay.io/skopeo/stable:v1.13.2 script: | set -ex From 09c092f7853ae1eca31df9c32eb5ef7c204e1ba4 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 30 Aug 2023 18:33:54 -0400 Subject: [PATCH 159/180] [batch] More debugging information for network namespace errors (#13509) In a previous PR we added exception logging when tasks on a `BackgroundTaskManager` fail. I'm not seeing any of those messages in the worker logs, suggesting that for some reason the Tasks to free a network namespace when a job is finished are not getting created in the first place. I don't see how in the code we could somehow *not* free the network namespace, but I'm hoping that some of these diagnostics shed some light. Also open to suggestions for where else might be a good spot to add more logging. --- .../batch/cloud/gcp/driver/create_instance.py | 11 ++++++++++ batch/batch/worker/worker.py | 20 ++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/batch/batch/cloud/gcp/driver/create_instance.py b/batch/batch/cloud/gcp/driver/create_instance.py index e3ad4b3f09d..44aa7876fb8 100644 --- a/batch/batch/cloud/gcp/driver/create_instance.py +++ b/batch/batch/cloud/gcp/driver/create_instance.py @@ -238,6 +238,17 @@ def scheduling() -> dict: EOF +sudo tee /etc/google-fluentd/config.d/syslog.conf < +@type tail +format syslog +path /var/log/syslog +pos_file /var/lib/google-fluentd/pos/syslog.pos +read_from_head true +tag syslog + +EOF + sudo tee /etc/google-fluentd/config.d/run-log.conf < @type tail diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index a758ccd7730..32a118f94de 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -965,6 +965,7 @@ async def _kill(self): self._killed = True async def _cleanup(self): + log.info(f'Cleaning up {self}') if self._cleaned_up: return @@ -987,6 +988,7 @@ async def _cleanup(self): if self.netns: assert network_allocator network_allocator.free(self.netns) + log.info(f'Freed the network namespace for {self}') self.netns = None finally: try: @@ -1026,12 +1028,16 @@ async def _setup_overlay(self): async def _setup_network_namespace(self): assert network_allocator assert port_allocator - async with async_timeout.timeout(60): - if self.network == 'private': - self.netns = await network_allocator.allocate_private() - else: - assert self.network is None or self.network == 'public' - self.netns = await network_allocator.allocate_public() + try: + async with async_timeout.timeout(60): + if self.network == 'private': + self.netns = await network_allocator.allocate_private() + else: + assert self.network is None or self.network == 'public' + self.netns = await network_allocator.allocate_public() + except asyncio.TimeoutError: + log.exception(network_allocator.task_manager.tasks) + raise if self.port is not None: self.host_port = await port_allocator.allocate() @@ -1847,7 +1853,7 @@ async def on_completion(): except asyncio.CancelledError: raise except Exception: - pass + log.exception(f'While running container: {container}') async def run(self): async with self.worker.cpu_sem(self.cpu_in_mcpu): From 228e98e25ef0c2bf1c5a66c06acf08ebeef6ca0b Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 30 Aug 2023 20:05:37 -0400 Subject: [PATCH 160/180] [batch] Name the batch worker container (#13519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Super tiny quality of life change, so one can `docker exec worker …` instead of copy/pasting the container id --- batch/batch/cloud/azure/driver/create_instance.py | 1 + batch/batch/cloud/gcp/driver/create_instance.py | 1 + 2 files changed, 2 insertions(+) diff --git a/batch/batch/cloud/azure/driver/create_instance.py b/batch/batch/cloud/azure/driver/create_instance.py index a24484fdc11..b820287cb03 100644 --- a/batch/batch/cloud/azure/driver/create_instance.py +++ b/batch/batch/cloud/azure/driver/create_instance.py @@ -246,6 +246,7 @@ def create_vm_config( # So here I go it's my shot. docker run \ +--name worker \ -e CLOUD=azure \ -e CORES=$CORES \ -e NAME=$NAME \ diff --git a/batch/batch/cloud/gcp/driver/create_instance.py b/batch/batch/cloud/gcp/driver/create_instance.py index 44aa7876fb8..dc2a8ff164a 100644 --- a/batch/batch/cloud/gcp/driver/create_instance.py +++ b/batch/batch/cloud/gcp/driver/create_instance.py @@ -337,6 +337,7 @@ def scheduling() -> dict: # So here I go it's my shot. docker run \ +--name worker \ -e CLOUD=gcp \ -e CORES=$CORES \ -e NAME=$NAME \ From 91f5a0bfc30927014b60b11a353a4d95db009427 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Wed, 30 Aug 2023 21:31:14 -0400 Subject: [PATCH 161/180] [lint] Add pre-commit to dev requirements (#13518) --- gear/pinned-requirements.txt | 17 +++++++++++++- hail/python/dev/pinned-requirements.txt | 31 +++++++++++++++++++------ hail/python/dev/requirements.txt | 1 + web_common/pinned-requirements.txt | 2 ++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/gear/pinned-requirements.txt b/gear/pinned-requirements.txt index 414d4efc818..157e539aa3b 100644 --- a/gear/pinned-requirements.txt +++ b/gear/pinned-requirements.txt @@ -11,10 +11,11 @@ aiohttp==3.8.5 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp-session + # aiomonitor # kubernetes-asyncio aiohttp-session==2.12.0 # via -r hail/gear/requirements.txt -aiomonitor==0.5.0 +aiomonitor==0.6.0 # via -r hail/gear/requirements.txt aiomysql==0.2.0 # via -r hail/gear/requirements.txt @@ -35,6 +36,8 @@ attrs==23.1.0 # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # aiomonitor +backports-strenum==1.2.4 + # via aiomonitor cachetools==5.3.1 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt @@ -108,8 +111,18 @@ janus==1.0.0 # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt # aiomonitor +jinja2==3.1.2 + # via + # -c hail/gear/../hail/python/dev/pinned-requirements.txt + # -c hail/gear/../hail/python/pinned-requirements.txt + # aiomonitor kubernetes-asyncio==19.15.1 # via -r hail/gear/requirements.txt +markupsafe==2.1.3 + # via + # -c hail/gear/../hail/python/dev/pinned-requirements.txt + # -c hail/gear/../hail/python/pinned-requirements.txt + # jinja2 multidict==6.0.4 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt @@ -197,6 +210,8 @@ sortedcontainers==2.4.0 # -r hail/gear/requirements.txt terminaltables==3.1.10 # via aiomonitor +trafaret==2.1.1 + # via aiomonitor typing-extensions==4.7.1 # via # -c hail/gear/../hail/python/dev/pinned-requirements.txt diff --git a/hail/python/dev/pinned-requirements.txt b/hail/python/dev/pinned-requirements.txt index 86a75fce1f6..495e3011ac9 100644 --- a/hail/python/dev/pinned-requirements.txt +++ b/hail/python/dev/pinned-requirements.txt @@ -46,6 +46,8 @@ cffi==1.15.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt # argon2-cffi-bindings +cfgv==3.4.0 + # via pre-commit charset-normalizer==3.2.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt @@ -80,6 +82,8 @@ dill==0.3.7 # via # -c hail/hail/python/dev/../pinned-requirements.txt # pylint +distlib==0.3.7 + # via virtualenv docutils==0.18.1 # via # nbsphinx @@ -95,12 +99,16 @@ executing==1.2.0 # via stack-data fastjsonschema==2.18.0 # via nbformat +filelock==3.12.3 + # via virtualenv fonttools==4.42.1 # via matplotlib fqdn==1.5.1 # via jsonschema fswatch==0.1.1 # via -r hail/hail/python/dev/requirements.txt +identify==2.5.27 + # via pre-commit idna==3.4 # via # -c hail/hail/python/dev/../pinned-requirements.txt @@ -169,7 +177,7 @@ jsonschema-specifications==2023.7.1 # via jsonschema jupyter==1.0.0 # via -r hail/hail/python/dev/requirements.txt -jupyter-client==8.3.0 +jupyter-client==8.3.1 # via # ipykernel # jupyter-console @@ -212,7 +220,7 @@ jupyterlab-server==2.24.0 # notebook jupyterlab-widgets==3.0.8 # via ipywidgets -kiwisolver==1.4.4 +kiwisolver==1.4.5 # via matplotlib lazy-object-proxy==1.9.0 # via astroid @@ -246,14 +254,16 @@ nbformat==5.9.2 # nbclient # nbconvert # nbsphinx -nbsphinx==0.9.2 +nbsphinx==0.9.3 # via -r hail/hail/python/dev/requirements.txt nest-asyncio==1.5.7 # via # -c hail/hail/python/dev/../pinned-requirements.txt # ipykernel nodeenv==1.8.0 - # via pyright + # via + # pre-commit + # pyright notebook==7.0.2 # via jupyter notebook-shim==0.2.3 @@ -305,8 +315,11 @@ platformdirs==3.10.0 # black # jupyter-core # pylint -pluggy==1.2.0 + # virtualenv +pluggy==1.3.0 # via pytest +pre-commit==3.3.3 + # via -r hail/hail/python/dev/requirements.txt prometheus-client==0.17.1 # via jupyter-server prompt-toolkit==3.0.39 @@ -384,6 +397,7 @@ pyyaml==6.0.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt # jupyter-events + # pre-commit pyzmq==25.1.1 # via # ipykernel @@ -413,11 +427,11 @@ rfc3986-validator==0.1.1 # via # jsonschema # jupyter-events -rpds-py==0.9.2 +rpds-py==0.10.0 # via # jsonschema # referencing -ruff==0.0.285 +ruff==0.0.286 # via -r hail/hail/python/dev/requirements.txt send2trash==1.8.2 # via jupyter-server @@ -537,6 +551,7 @@ typing-extensions==4.7.1 # astroid # async-lru # black + # filelock # ipython # pylint uri-template==1.3.0 @@ -545,6 +560,8 @@ urllib3==1.26.16 # via # -c hail/hail/python/dev/../pinned-requirements.txt # requests +virtualenv==20.24.3 + # via pre-commit wcwidth==0.2.6 # via prompt-toolkit webcolors==1.13 diff --git a/hail/python/dev/requirements.txt b/hail/python/dev/requirements.txt index 75b0f8f5c5f..f8ef07cbd77 100644 --- a/hail/python/dev/requirements.txt +++ b/hail/python/dev/requirements.txt @@ -1,6 +1,7 @@ -c ../pinned-requirements.txt pylint>=2.13.5,<3 +pre-commit>=3.3.3,<4 black>=22.8.0,<23 ruff>=0.0.264,<1 curlylint>=0.13.1,<1 diff --git a/web_common/pinned-requirements.txt b/web_common/pinned-requirements.txt index a38db95428e..abdd6465451 100644 --- a/web_common/pinned-requirements.txt +++ b/web_common/pinned-requirements.txt @@ -47,6 +47,7 @@ idna==3.4 # yarl jinja2==3.1.2 # via + # -c hail/web_common/../gear/pinned-requirements.txt # -c hail/web_common/../hail/python/dev/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt # -r hail/web_common/requirements.txt @@ -55,6 +56,7 @@ libsass==0.22.0 # via -r hail/web_common/requirements.txt markupsafe==2.1.3 # via + # -c hail/web_common/../gear/pinned-requirements.txt # -c hail/web_common/../hail/python/dev/pinned-requirements.txt # -c hail/web_common/../hail/python/pinned-requirements.txt # jinja2 From b1a1f81a153a8b10ca64d3fbd85c185ea4ade02c Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 31 Aug 2023 18:36:48 -0400 Subject: [PATCH 162/180] [batch] treat search field as plaintext: no spellcheck, no autocorrect (#13497) Without this my browser keeps trying to put periods everywhere. --------- Co-authored-by: iris <84595986+iris-garden@users.noreply.github.com> --- batch/batch/front_end/templates/table_search.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/batch/batch/front_end/templates/table_search.html b/batch/batch/front_end/templates/table_search.html index 6116c73336b..00c3736f231 100644 --- a/batch/batch/front_end/templates/table_search.html +++ b/batch/batch/front_end/templates/table_search.html @@ -49,7 +49,7 @@
- +
From 5d57d091bb91e9321b3317c6e54353c348962f77 Mon Sep 17 00:00:00 2001 From: Christopher Vittal Date: Thu, 31 Aug 2023 20:08:29 -0400 Subject: [PATCH 163/180] [query] All non-spark task context use in using blocks (#13534) This will ensure proper freeing of resources, no matter what. --- .../is/hail/backend/local/LocalBackend.scala | 8 ++++---- .../scala/is/hail/backend/service/Worker.scala | 15 ++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala b/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala index 5daa3a4a50b..9287d5059c2 100644 --- a/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala +++ b/hail/src/main/scala/is/hail/backend/local/LocalBackend.scala @@ -128,10 +128,10 @@ class LocalBackend( ): Array[Array[Byte]] = { val stageId = nextStageId() collection.zipWithIndex.map { case (c, i) => - val htc = new LocalTaskContext(i, stageId) - val bytes = f(c, htc, theHailClassLoader, fs) - htc.close() - bytes + using(new LocalTaskContext(i, stageId)) { htc => + val bytes = f(c, htc, theHailClassLoader, fs) + bytes + } } } diff --git a/hail/src/main/scala/is/hail/backend/service/Worker.scala b/hail/src/main/scala/is/hail/backend/service/Worker.scala index 23ec040fb4d..d6665c8f405 100644 --- a/hail/src/main/scala/is/hail/backend/service/Worker.scala +++ b/hail/src/main/scala/is/hail/backend/service/Worker.scala @@ -160,17 +160,18 @@ object Worker { // FIXME: workers should not have backends, but some things do need hail contexts new ServiceBackend(null, null, new HailClassLoader(getClass().getClassLoader()), null, None)) } - val htc = new ServiceTaskContext(i) + var result: Array[Byte] = null var userError: HailException = null - try { - retryTransientErrors { - result = f(context, htc, theHailClassLoader, fs) + using(new ServiceTaskContext(i)) { htc => + try { + retryTransientErrors { + result = f(context, htc, theHailClassLoader, fs) + } + } catch { + case err: HailException => userError = err } - } catch { - case err: HailException => userError = err } - htc.close() timer.end("executeFunction") timer.start("writeOutputs") From a2f29c362a52d98078cf60f70425a8b392d7e591 Mon Sep 17 00:00:00 2001 From: Dan King Date: Thu, 31 Aug 2023 21:30:14 -0400 Subject: [PATCH 164/180] [query] fix pickling of hl.Struct (#13523) CHANGELOG: `hl.Struct` is now pickle-able. --- hail/python/hail/utils/struct.py | 7 +++++ hail/python/test/hail/utils/test_pickle.py | 33 ++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 hail/python/test/hail/utils/test_pickle.py diff --git a/hail/python/hail/utils/struct.py b/hail/python/hail/utils/struct.py index a2ff7df7bec..658c25175f9 100644 --- a/hail/python/hail/utils/struct.py +++ b/hail/python/hail/utils/struct.py @@ -1,3 +1,4 @@ +from typing import Dict, Any from collections import OrderedDict from collections.abc import Mapping import pprint @@ -50,6 +51,12 @@ def __init__(self, **kwargs): def __contains__(self, item): return item in self._fields + def __getstate__(self) -> Dict[str, Any]: + return self._fields + + def __setstate__(self, state: Dict[str, Any]): + self.__dict__["_fields"] = state + def _get_field(self, item): if item in self._fields: return self._fields[item] diff --git a/hail/python/test/hail/utils/test_pickle.py b/hail/python/test/hail/utils/test_pickle.py new file mode 100644 index 00000000000..e51337848c7 --- /dev/null +++ b/hail/python/test/hail/utils/test_pickle.py @@ -0,0 +1,33 @@ +import pickle +import dill +import hail as hl + + +def test_simple_struct_pickle(): + x = hl.Struct(key='group', value='adj') + assert x == pickle.loads(pickle.dumps(x)) + + +def test_simple_struct_dill(): + x = hl.Struct(key='group', value='adj') + assert x == dill.loads(dill.dumps(x)) + + +def test_frozendict_pickle(): + x = {hl.utils.frozendict({'abc': 123, 'def': 'hello'}): 10} + assert x == pickle.loads(pickle.dumps(x)) + + +def test_frozendict_dill(): + x = {hl.utils.frozendict({'abc': 123, 'def': 'hello'}): 10} + assert x == dill.loads(dill.dumps(x)) + + +def test_locus_pickle(): + x = hl.Locus('1', 123) + assert x == pickle.loads(pickle.dumps(x)) + + +def test_locus_dill(): + x = hl.Locus('1', 123) + assert x == dill.loads(dill.dumps(x)) From 07a483ae0f46c66f3ed6fd265b48f48c06298f98 Mon Sep 17 00:00:00 2001 From: jigold Date: Thu, 31 Aug 2023 22:46:35 -0400 Subject: [PATCH 165/180] [batch] Show cost breakdown in the UI (#13491) Fixes #13483 Screenshot 2023-08-24 at 2 46 17 PM Screenshot 2023-08-24 at 2 39 57 PM Screenshot 2023-08-24 at 2 39 48 PM --- batch/batch/batch.py | 12 +++++ batch/batch/driver/job.py | 34 ++++++++----- batch/batch/front_end/front_end.py | 59 ++++++++++++---------- batch/batch/front_end/query/query_v1.py | 37 ++++++++------ batch/batch/front_end/query/query_v2.py | 9 ++-- batch/batch/front_end/templates/batch.html | 22 ++++++++ batch/batch/front_end/templates/job.html | 22 ++++++++ batch/test/test_dag.py | 1 + hail/python/hailtop/utils/utils.py | 4 ++ 9 files changed, 141 insertions(+), 59 deletions(-) diff --git a/batch/batch/batch.py b/batch/batch/batch.py index 52dc7d2e949..fcfc4e41058 100644 --- a/batch/batch/batch.py +++ b/batch/batch/batch.py @@ -12,6 +12,10 @@ log = logging.getLogger('batch') +def cost_breakdown_to_dict(cost_breakdown: dict): + return [{'resource': resource, 'cost': cost} for resource, cost in cost_breakdown.items()] + + def batch_record_to_dict(record: Dict[str, Any]) -> Dict[str, Any]: if record['state'] == 'open': state = 'open' @@ -39,6 +43,9 @@ def _time_msecs_str(t): else: duration = None + if record['cost_breakdown'] is not None: + record['cost_breakdown'] = cost_breakdown_to_dict(json.loads(record['cost_breakdown'])) + d = { 'id': record['id'], 'user': record['user'], @@ -58,6 +65,7 @@ def _time_msecs_str(t): 'duration': duration, 'msec_mcpu': record['msec_mcpu'], 'cost': coalesce(record['cost'], 0), + 'cost_breakdown': record['cost_breakdown'], } attributes = json.loads(record['attributes']) @@ -78,6 +86,9 @@ def job_record_to_dict(record: Dict[str, Any], name: Optional[str]) -> Dict[str, exit_code = None duration = None + if record['cost_breakdown'] is not None: + record['cost_breakdown'] = cost_breakdown_to_dict(json.loads(record['cost_breakdown'])) + result = { 'batch_id': record['batch_id'], 'job_id': record['job_id'], @@ -89,6 +100,7 @@ def job_record_to_dict(record: Dict[str, Any], name: Optional[str]) -> Dict[str, 'duration': duration, 'cost': coalesce(record['cost'], 0), 'msec_mcpu': record['msec_mcpu'], + 'cost_breakdown': record['cost_breakdown'], } return result diff --git a/batch/batch/driver/job.py b/batch/batch/driver/job.py index 7d5f95988f9..266eb50832b 100644 --- a/batch/batch/driver/job.py +++ b/batch/batch/driver/job.py @@ -31,26 +31,34 @@ async def notify_batch_job_complete(db: Database, client_session: httpx.ClientSession, batch_id): record = await db.select_and_fetchone( ''' -SELECT batches.*, COALESCE(SUM(`usage` * rate), 0) AS cost, batches_cancelled.id IS NOT NULL AS cancelled, batches_n_jobs_in_complete_states.n_completed, batches_n_jobs_in_complete_states.n_succeeded, batches_n_jobs_in_complete_states.n_failed, batches_n_jobs_in_complete_states.n_cancelled +SELECT batches.*, + cost_t.cost, + cost_t.cost_breakdown, + batches_cancelled.id IS NOT NULL AS cancelled, + batches_n_jobs_in_complete_states.n_completed, + batches_n_jobs_in_complete_states.n_succeeded, + batches_n_jobs_in_complete_states.n_failed, + batches_n_jobs_in_complete_states.n_cancelled FROM batches LEFT JOIN batches_n_jobs_in_complete_states ON batches.id = batches_n_jobs_in_complete_states.id -LEFT JOIN ( - SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM aggregated_batch_resources_v2 - WHERE batch_id = %s - GROUP BY batch_id, resource_id -) AS abr - ON batches.id = abr.batch_id -LEFT JOIN resources - ON abr.resource_id = resources.resource_id +LEFT JOIN LATERAL ( + SELECT COALESCE(SUM(`usage` * rate), 0) AS cost, JSON_OBJECTAGG(resources.resource, COALESCE(`usage` * rate, 0)) AS cost_breakdown + FROM ( + SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` + FROM aggregated_batch_resources_v2 + WHERE batches.id = aggregated_batch_resources_v2.batch_id + GROUP BY batch_id, resource_id + ) AS usage_t + LEFT JOIN resources ON usage_t.resource_id = resources.resource_id + GROUP BY batch_id +) AS cost_t ON TRUE LEFT JOIN batches_cancelled ON batches.id = batches_cancelled.id WHERE batches.id = %s AND NOT deleted AND callback IS NOT NULL AND - batches.`state` = 'complete' -GROUP BY batches.id; + batches.`state` = 'complete'; ''', - (batch_id, batch_id), + (batch_id,), 'notify_batch_job_complete', ) diff --git a/batch/batch/front_end/front_end.py b/batch/batch/front_end/front_end.py index a701223c9ca..68fd981df8c 100644 --- a/batch/batch/front_end/front_end.py +++ b/batch/batch/front_end/front_end.py @@ -1467,30 +1467,30 @@ async def _get_batch(app, batch_id): record = await db.select_and_fetchone( ''' -WITH base_t AS ( SELECT batches.*, batches_cancelled.id IS NOT NULL AS cancelled, batches_n_jobs_in_complete_states.n_completed, batches_n_jobs_in_complete_states.n_succeeded, batches_n_jobs_in_complete_states.n_failed, - batches_n_jobs_in_complete_states.n_cancelled + batches_n_jobs_in_complete_states.n_cancelled, + cost_t.* FROM batches LEFT JOIN batches_n_jobs_in_complete_states ON batches.id = batches_n_jobs_in_complete_states.id LEFT JOIN batches_cancelled ON batches.id = batches_cancelled.id -WHERE batches.id = %s AND NOT deleted -) -SELECT base_t.*, COALESCE(SUM(`usage` * rate), 0) AS cost -FROM base_t -LEFT JOIN ( - SELECT aggregated_batch_resources_v2.batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM base_t - LEFT JOIN aggregated_batch_resources_v2 ON base_t.id = aggregated_batch_resources_v2.batch_id - GROUP BY aggregated_batch_resources_v2.batch_id, aggregated_batch_resources_v2.resource_id -) AS usage_t ON base_t.id = usage_t.batch_id -LEFT JOIN resources ON usage_t.resource_id = resources.resource_id -GROUP BY base_t.id; +LEFT JOIN LATERAL ( + SELECT COALESCE(SUM(`usage` * rate), 0) AS cost, JSON_OBJECTAGG(resources.resource, COALESCE(`usage` * rate, 0)) AS cost_breakdown + FROM ( + SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` + FROM aggregated_batch_resources_v2 + WHERE batches.id = aggregated_batch_resources_v2.batch_id + GROUP BY batch_id, resource_id + ) AS usage_t + LEFT JOIN resources ON usage_t.resource_id = resources.resource_id + GROUP BY batch_id +) AS cost_t ON TRUE +WHERE batches.id = %s AND NOT deleted; ''', (batch_id,), ) @@ -1666,6 +1666,11 @@ async def ui_batch(request, userdata, batch_id): batch['cost'] = cost_str(batch['cost']) + if batch['cost_breakdown'] is not None: + for record in batch['cost_breakdown']: + record['cost'] = cost_str(record['cost']) + batch['cost_breakdown'].sort(key=lambda record: record['resource']) + page_context = { 'batch': batch, 'q': q, @@ -1759,21 +1764,18 @@ async def _get_job(app, batch_id, job_id): ON jobs.batch_id = batch_updates.batch_id AND jobs.update_id = batch_updates.update_id WHERE jobs.batch_id = %s AND NOT deleted AND jobs.job_id = %s AND batch_updates.committed ) -SELECT base_t.*, COALESCE(SUM(`usage` * rate), 0) AS cost +SELECT base_t.*, cost_t.cost, cost_t.cost_breakdown FROM base_t -LEFT JOIN ( - SELECT aggregated_job_resources_v2.batch_id, - aggregated_job_resources_v2.job_id, - aggregated_job_resources_v2.resource_id, - CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM base_t - LEFT JOIN aggregated_job_resources_v2 - ON aggregated_job_resources_v2.batch_id = base_t.batch_id AND - aggregated_job_resources_v2.job_id = base_t.job_id +LEFT JOIN LATERAL ( +SELECT COALESCE(SUM(`usage` * rate), 0) AS cost, JSON_OBJECTAGG(resources.resource, COALESCE(`usage` * rate, 0)) AS cost_breakdown +FROM (SELECT aggregated_job_resources_v2.batch_id, aggregated_job_resources_v2.job_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` + FROM aggregated_job_resources_v2 + WHERE aggregated_job_resources_v2.batch_id = base_t.batch_id AND aggregated_job_resources_v2.job_id = base_t.job_id GROUP BY aggregated_job_resources_v2.batch_id, aggregated_job_resources_v2.job_id, aggregated_job_resources_v2.resource_id -) AS usage_t ON usage_t.batch_id = base_t.batch_id AND usage_t.job_id = base_t.job_id +) AS usage_t LEFT JOIN resources ON usage_t.resource_id = resources.resource_id -GROUP BY base_t.batch_id, base_t.job_id, base_t.last_cancelled_attempt_id; +GROUP BY usage_t.batch_id, usage_t.job_id +) AS cost_t ON TRUE; ''', (batch_id, job_id, batch_id, job_id), ) @@ -2073,6 +2075,11 @@ async def ui_get_job(request, userdata, batch_id): job['duration'] = humanize_timedelta_msecs(job['duration']) job['cost'] = cost_str(job['cost']) + if job['cost_breakdown'] is not None: + for record in job['cost_breakdown']: + record['cost'] = cost_str(record['cost']) + job['cost_breakdown'].sort(key=lambda record: record['resource']) + job_status = job['status'] container_status_spec = dictfix.NoneOr( { diff --git a/batch/batch/front_end/query/query_v1.py b/batch/batch/front_end/query/query_v1.py index 2833bb216d8..138495dfc26 100644 --- a/batch/batch/front_end/query/query_v1.py +++ b/batch/batch/front_end/query/query_v1.py @@ -102,16 +102,19 @@ def parse_list_batches_query_v1(user: str, q: str, last_batch_id: Optional[int]) ORDER BY id DESC LIMIT 51 ) -SELECT base_t.*, COALESCE(SUM(`usage` * rate), 0) AS cost +SELECT base_t.*, cost_t.cost, cost_t.cost_breakdown FROM base_t -LEFT JOIN ( - SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM base_t - LEFT JOIN aggregated_batch_resources_v2 ON base_t.id = aggregated_batch_resources_v2.batch_id - GROUP BY batch_id, resource_id -) AS usage_t ON base_t.id = usage_t.batch_id -LEFT JOIN resources ON usage_t.resource_id = resources.resource_id -GROUP BY id +LEFT JOIN LATERAL ( + SELECT COALESCE(SUM(`usage` * rate), 0) AS cost, JSON_OBJECTAGG(resources.resource, COALESCE(`usage` * rate, 0)) AS cost_breakdown + FROM ( + SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` + FROM aggregated_batch_resources_v2 + WHERE base_t.id = aggregated_batch_resources_v2.batch_id + GROUP BY batch_id, resource_id + ) AS usage_t + LEFT JOIN resources ON usage_t.resource_id = resources.resource_id + GROUP BY batch_id +) AS cost_t ON TRUE ORDER BY id DESC; ''' @@ -187,16 +190,18 @@ def parse_batch_jobs_query_v1(batch_id: int, q: str, last_job_id: Optional[int]) WHERE {' AND '.join(where_conditions)} LIMIT 50 ) -SELECT base_t.*, COALESCE(SUM(`usage` * rate), 0) AS cost +SELECT base_t.*, cost_t.cost, cost_t.cost_breakdown FROM base_t -LEFT JOIN ( - SELECT aggregated_job_resources_v2.batch_id, aggregated_job_resources_v2.job_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` - FROM base_t - LEFT JOIN aggregated_job_resources_v2 ON base_t.batch_id = aggregated_job_resources_v2.batch_id AND base_t.job_id = aggregated_job_resources_v2.job_id +LEFT JOIN LATERAL ( +SELECT COALESCE(SUM(`usage` * rate), 0) AS cost, JSON_OBJECTAGG(resources.resource, COALESCE(`usage` * rate, 0)) AS cost_breakdown +FROM (SELECT aggregated_job_resources_v2.batch_id, aggregated_job_resources_v2.job_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` + FROM aggregated_job_resources_v2 + WHERE aggregated_job_resources_v2.batch_id = base_t.batch_id AND aggregated_job_resources_v2.job_id = base_t.job_id GROUP BY aggregated_job_resources_v2.batch_id, aggregated_job_resources_v2.job_id, aggregated_job_resources_v2.resource_id -) AS usage_t ON base_t.batch_id = usage_t.batch_id AND base_t.job_id = usage_t.job_id +) AS usage_t LEFT JOIN resources ON usage_t.resource_id = resources.resource_id -GROUP BY base_t.batch_id, base_t.job_id; +GROUP BY usage_t.batch_id, usage_t.job_id +) AS cost_t ON TRUE; ''' return (sql, where_args) diff --git a/batch/batch/front_end/query/query_v2.py b/batch/batch/front_end/query/query_v2.py index 275c6daefe3..2b3da9248a6 100644 --- a/batch/batch/front_end/query/query_v2.py +++ b/batch/batch/front_end/query/query_v2.py @@ -133,14 +133,14 @@ def parse_list_batches_query_v2(user: str, q: str, last_batch_id: Optional[int]) batches_n_jobs_in_complete_states.n_succeeded, batches_n_jobs_in_complete_states.n_failed, batches_n_jobs_in_complete_states.n_cancelled, - cost_t.cost + cost_t.cost, cost_t.cost_breakdown FROM batches LEFT JOIN billing_projects ON batches.billing_project = billing_projects.name LEFT JOIN batches_n_jobs_in_complete_states ON batches.id = batches_n_jobs_in_complete_states.id LEFT JOIN batches_cancelled ON batches.id = batches_cancelled.id STRAIGHT_JOIN billing_project_users ON batches.billing_project = billing_project_users.billing_project LEFT JOIN LATERAL ( - SELECT COALESCE(SUM(`usage` * rate), 0) AS cost + SELECT COALESCE(SUM(`usage` * rate), 0) AS cost, JSON_OBJECTAGG(resources.resource, COALESCE(`usage` * rate, 0)) AS cost_breakdown FROM ( SELECT batch_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` FROM aggregated_batch_resources_v2 @@ -269,7 +269,8 @@ def parse_batch_jobs_query_v2(batch_id: int, q: str, last_job_id: Optional[int]) attempts_table_join_str = '' sql = f''' -SELECT jobs.*, batches.user, batches.billing_project, batches.format_version, job_attributes.value AS name, cost_t.cost +SELECT jobs.*, batches.user, batches.billing_project, batches.format_version, job_attributes.value AS name, cost_t.cost, + cost_t.cost_breakdown FROM jobs INNER JOIN batches ON jobs.batch_id = batches.id INNER JOIN batch_updates ON jobs.batch_id = batch_updates.batch_id AND jobs.update_id = batch_updates.update_id @@ -279,7 +280,7 @@ def parse_batch_jobs_query_v2(batch_id: int, q: str, last_job_id: Optional[int]) job_attributes.`key` = 'name' {attempts_table_join_str} LEFT JOIN LATERAL ( -SELECT COALESCE(SUM(`usage` * rate), 0) AS cost +SELECT COALESCE(SUM(`usage` * rate), 0) AS cost, JSON_OBJECTAGG(resources.resource, COALESCE(`usage` * rate, 0)) AS cost_breakdown FROM (SELECT aggregated_job_resources_v2.batch_id, aggregated_job_resources_v2.job_id, resource_id, CAST(COALESCE(SUM(`usage`), 0) AS SIGNED) AS `usage` FROM aggregated_job_resources_v2 WHERE aggregated_job_resources_v2.batch_id = jobs.batch_id AND aggregated_job_resources_v2.job_id = jobs.job_id diff --git a/batch/batch/front_end/templates/batch.html b/batch/batch/front_end/templates/batch.html index 817260f4aaf..161b0856dee 100644 --- a/batch/batch/front_end/templates/batch.html +++ b/batch/batch/front_end/templates/batch.html @@ -42,6 +42,28 @@

Attributes

{% endfor %} {% endif %} +

Cost Breakdown

+{% if batch['cost_breakdown'] %} +
+ + + + + + + + {% for resource_cost in batch['cost_breakdown'] %} + + + + + {% endfor %} + +
ResourceCost
{{ resource_cost['resource'] }}{{ resource_cost['cost'] }}
+{% else %} +

No accrued costs

+{% endif %} +

Jobs

{{ table_search("job-search", base_path ~ "/batches/" ~ batch["id"]) }} diff --git a/batch/batch/front_end/templates/job.html b/batch/batch/front_end/templates/job.html index 955978ef97e..3b0c425c263 100644 --- a/batch/batch/front_end/templates/job.html +++ b/batch/batch/front_end/templates/job.html @@ -15,6 +15,28 @@

Properties

  • Cost: {% if 'cost' in job and job['cost'] is not none %}{{ job['cost'] }}{% endif %}
  • +

    Cost Breakdown

    +{% if job['cost_breakdown'] %} + + + + + + + + + {% for resource_cost in job['cost_breakdown'] %} + + + + + {% endfor %} + +
    ResourceCost
    {{ resource_cost['resource'] }}{{ resource_cost['cost'] }}
    +{% else %} +

    No accrued costs

    +{% endif %} +

    Attempts

    {% if attempts %} diff --git a/batch/test/test_dag.py b/batch/test/test_dag.py index 9989e5676bd..53cfc7c93ea 100644 --- a/batch/test/test_dag.py +++ b/batch/test/test_dag.py @@ -160,6 +160,7 @@ async def callback(request): callback_body.pop('time_closed') callback_body.pop('time_completed') callback_body.pop('duration') + callback_body.pop('cost_breakdown') assert callback_body == { 'id': b.id, 'user': 'test', diff --git a/hail/python/hailtop/utils/utils.py b/hail/python/hailtop/utils/utils.py index 386f26eaa40..ba0b0eea65d 100644 --- a/hail/python/hailtop/utils/utils.py +++ b/hail/python/hailtop/utils/utils.py @@ -77,6 +77,10 @@ def first_extant_file(*files: Optional[str]) -> Optional[str]: def cost_str(cost: Optional[int]) -> Optional[str]: if cost is None: return None + if cost == 0.0: + return '$0.0000' + if cost < 0.0001: + return '<$0.0001' return f'${cost:.4f}' From a22168baa5d914536dc738df9ae62ffef710c130 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 1 Sep 2023 12:32:11 -0400 Subject: [PATCH 166/180] [batch] re-allow sending kwargs to python jobs (#13505) CHANGELOG: Fix bug introduced in 0.2.117 by commit `c9de81108` which prevented the passing of keyword arguments to Python jobs. This manifested as "ValueError: too many values to unpack". We also weren't preserving tuples. They become lists. I fixed that too. I also added some types and avoided an is instance by encoding the necessary knowledge. --- devbin/generate_gcp_ar_cleanup_policy.py | 50 +++++++++---------- hail/python/hailtop/batch/job.py | 51 ++++++++++++++------ hail/python/hailtop/batch/resource.py | 5 +- hail/python/test/hailtop/batch/test_batch.py | 44 +++++++++++++++++ hail/scripts/test_requester_pays_parsing.py | 2 +- 5 files changed, 108 insertions(+), 44 deletions(-) diff --git a/devbin/generate_gcp_ar_cleanup_policy.py b/devbin/generate_gcp_ar_cleanup_policy.py index f8dcc4f1591..b027e9fb849 100644 --- a/devbin/generate_gcp_ar_cleanup_policy.py +++ b/devbin/generate_gcp_ar_cleanup_policy.py @@ -12,15 +12,17 @@ def to_dict(self): class DeletePolicy(CleanupPolicy): - def __init__(self, - name: str, - tag_state: str, - *, - tag_prefixes: Optional[List[str]] = None, - version_name_prefixes: Optional[List[str]] = None, - package_name_prefixes: Optional[List[str]] = None, - older_than: Optional[str] = None, - newer_than: Optional[str] = None): + def __init__( + self, + name: str, + tag_state: str, + *, + tag_prefixes: Optional[List[str]] = None, + version_name_prefixes: Optional[List[str]] = None, + package_name_prefixes: Optional[List[str]] = None, + older_than: Optional[str] = None, + newer_than: Optional[str] = None + ): self.name = name self.tag_state = tag_state self.tag_prefixes = tag_prefixes @@ -46,15 +48,17 @@ def to_dict(self): class ConditionalKeepPolicy(CleanupPolicy): - def __init__(self, - name: str, - tag_state: str, - *, - tag_prefixes: Optional[List[str]] = None, - version_name_prefixes: Optional[List[str]] = None, - package_name_prefixes: Optional[List[str]] = None, - older_than: Optional[str] = None, - newer_than: Optional[str] = None): + def __init__( + self, + name: str, + tag_state: str, + *, + tag_prefixes: Optional[List[str]] = None, + version_name_prefixes: Optional[List[str]] = None, + package_name_prefixes: Optional[List[str]] = None, + older_than: Optional[str] = None, + newer_than: Optional[str] = None + ): self.name = name self.tag_state = tag_state self.tag_prefixes = tag_prefixes @@ -80,10 +84,7 @@ def to_dict(self): class MostRecentVersionKeepPolicy(CleanupPolicy): - def __init__(self, - name: str, - package_name_prefixes: List[str], - keep_count: int): + def __init__(self, name: str, package_name_prefixes: List[str], keep_count: int): self.name = name self.package_name_prefixes = package_name_prefixes self.keep_count = keep_count @@ -92,10 +93,7 @@ def to_dict(self): data = { 'name': self.name, 'action': {'type': 'Keep'}, - 'mostRecentVersions': { - 'packageNamePrefixes': self.package_name_prefixes, - 'keepCount': self.keep_count - } + 'mostRecentVersions': {'packageNamePrefixes': self.package_name_prefixes, 'keepCount': self.keep_count}, } return data diff --git a/hail/python/hailtop/batch/job.py b/hail/python/hailtop/batch/job.py index 9085ffe3fb8..a38be18c58b 100644 --- a/hail/python/hailtop/batch/job.py +++ b/hail/python/hailtop/batch/job.py @@ -5,7 +5,7 @@ import textwrap import warnings from shlex import quote as shq -from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union, cast +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union, cast, Literal from typing_extensions import Self import hailtop.batch_client.client as bc @@ -878,6 +878,19 @@ async def _compile(self, local_tmpdir, remote_tmpdir, *, dry_run=False): return True +UnpreparedArg = Union['_resource.ResourceType', List['UnpreparedArg'], Tuple['UnpreparedArg', ...], Dict[str, 'UnpreparedArg'], Any] + +PreparedArg = Union[ + Tuple[Literal['py_path'], str], + Tuple[Literal['path'], str], + Tuple[Literal['dict_path'], Dict[str, str]], + Tuple[Literal['list'], List['PreparedArg']], + Tuple[Literal['dict'], Dict[str, 'PreparedArg']], + Tuple[Literal['tuple'], Tuple['PreparedArg', ...]], + Tuple[Literal['value'], Any] +] + + class PythonJob(Job): """ Object representing a single Python job to execute. @@ -924,7 +937,7 @@ def __init__(self, super().__init__(batch, token, name=name, attributes=attributes, shell=None) self._resources: Dict[str, _resource.Resource] = {} self._resources_inverse: Dict[_resource.Resource, str] = {} - self._function_calls: List[Tuple[_resource.PythonResult, int, Tuple[Any, ...], Dict[str, Any]]] = [] + self._function_calls: List[Tuple[_resource.PythonResult, int, Tuple[UnpreparedArg, ...], Dict[str, UnpreparedArg]]] = [] self.n_results = 0 def _get_python_resource(self, item: str) -> '_resource.PythonResult': @@ -970,7 +983,7 @@ def image(self, image: str) -> 'PythonJob': self._image = image return self - def call(self, unapplied: Callable, *args, **kwargs) -> '_resource.PythonResult': + def call(self, unapplied: Callable, *args: UnpreparedArg, **kwargs: UnpreparedArg) -> '_resource.PythonResult': """Execute a Python function. Examples @@ -1148,7 +1161,7 @@ def handle_args(r): return result async def _compile(self, local_tmpdir, remote_tmpdir, *, dry_run=False): - def prepare_argument_for_serialization(arg): + def preserialize(arg: UnpreparedArg) -> PreparedArg: if isinstance(arg, _resource.PythonResult): return ('py_path', arg._get_path(local_tmpdir)) if isinstance(arg, _resource.ResourceFile): @@ -1156,20 +1169,24 @@ def prepare_argument_for_serialization(arg): if isinstance(arg, _resource.ResourceGroup): return ('dict_path', {name: resource._get_path(local_tmpdir) for name, resource in arg._resources.items()}) - if isinstance(arg, (list, tuple)): - return ('value', [prepare_argument_for_serialization(elt) for elt in arg]) + if isinstance(arg, list): + return ('list', [preserialize(elt) for elt in arg]) + if isinstance(arg, tuple): + return ('tuple', tuple((preserialize(elt) for elt in arg))) if isinstance(arg, dict): - return ('value', {k: prepare_argument_for_serialization(v) for k, v in arg.items()}) + return ('dict', {k: preserialize(v) for k, v in arg.items()}) return ('value', arg) for i, (result, unapplied_id, args, kwargs) in enumerate(self._function_calls): func_file = self._batch._python_function_files[unapplied_id] - prepared_args = prepare_argument_for_serialization(args)[1] - prepared_kwargs = prepare_argument_for_serialization(kwargs)[1] + preserialized_args = [preserialize(arg) for arg in args] + del args + preserialized_kwargs = {keyword: preserialize(arg) for keyword, arg in kwargs.items()} + del kwargs args_file = await self._batch._serialize_python_to_input_file( - os.path.dirname(result._get_path(remote_tmpdir)), "args", i, (prepared_args, prepared_kwargs), dry_run + os.path.dirname(result._get_path(remote_tmpdir)), "args", i, (preserialized_args, preserialized_kwargs), dry_run ) json_write, str_write, repr_write = [ @@ -1191,14 +1208,16 @@ def prepare_argument_for_serialization(arg): def deserialize_argument(arg): typ, val = arg - if typ == 'value' and isinstance(val, dict): - return {{k: deserialize_argument(v) for k, v in val.items()}} - if typ == 'value' and isinstance(val, (list, tuple)): - return [deserialize_argument(elt) for elt in val] if typ == 'py_path': return dill.load(open(val, 'rb')) if typ in ('path', 'dict_path'): return val + if typ == 'list': + return [deserialize_argument(elt) for elt in val] + if typ == 'tuple': + return tuple((deserialize_argument(elt) for elt in val)) + if typ == 'dict': + return {{k: deserialize_argument(v) for k, v in val.items()}} assert typ == 'value' return val @@ -1226,8 +1245,8 @@ def deserialize_argument(arg): unapplied = self._batch._python_function_defs[unapplied_id] self._user_code.append(textwrap.dedent(inspect.getsource(unapplied))) - args_str = ', '.join([f'{arg!r}' for _, arg in prepared_args]) - kwargs_str = ', '.join([f'{k}={v!r}' for k, (_, v) in kwargs.items()]) + args_str = ', '.join([f'{arg!r}' for _, arg in preserialized_args]) + kwargs_str = ', '.join([f'{k}={v!r}' for k, (_, v) in preserialized_kwargs.items()]) separator = ', ' if args_str and kwargs_str else '' func_call = f'{unapplied.__name__}({args_str}{separator}{kwargs_str})' self._user_code.append(self._interpolate_command(func_call, allow_python_results=True)) diff --git a/hail/python/hailtop/batch/resource.py b/hail/python/hailtop/batch/resource.py index b8df03ddca0..799d80e8daf 100644 --- a/hail/python/hailtop/batch/resource.py +++ b/hail/python/hailtop/batch/resource.py @@ -1,5 +1,5 @@ import abc -from typing import Optional, Set, cast +from typing import Optional, Set, cast, Union from . import job # pylint: disable=cyclic-import from .exceptions import BatchException @@ -448,3 +448,6 @@ def __str__(self): def __repr__(self): return self._uid # pylint: disable=no-member + + +ResourceType = Union[PythonResult, ResourceFile, ResourceGroup] diff --git a/hail/python/test/hailtop/batch/test_batch.py b/hail/python/test/hailtop/batch/test_batch.py index e66228ddbd6..efcc88d9d97 100644 --- a/hail/python/test/hailtop/batch/test_batch.py +++ b/hail/python/test/hailtop/batch/test_batch.py @@ -10,7 +10,10 @@ from shlex import quote as shq import uuid import re +import orjson +import hailtop.fs as hfs +import hailtop.batch_client.client as bc from hailtop import pip_version from hailtop.batch import Batch, ServiceBackend, LocalBackend, ResourceGroup from hailtop.batch.resource import JobResourceFile @@ -1291,6 +1294,47 @@ def test_update_batch_from_batch_id(self): res_status = res.status() assert res_status['state'] == 'success', str((res_status, res.debug_info())) + def test_python_job_with_kwarg(self): + def foo(*, kwarg): + return kwarg + + b = self.batch(default_python_image=PYTHON_DILL_IMAGE) + j = b.new_python_job() + r = j.call(foo, kwarg='hello world') + + output_path = f'{self.cloud_output_dir}/test_python_job_with_kwarg' + b.write_output(r.as_json(), output_path) + res = b.run() + assert isinstance(res, bc.Batch) + + assert res.status()['state'] == 'success', str((res, res.debug_info())) + with hfs.open(output_path) as f: + assert orjson.loads(f.read()) == 'hello world' + + def test_tuple_recursive_resource_extraction_in_python_jobs(self): + b = self.batch(default_python_image=PYTHON_DILL_IMAGE) + + def write(paths): + if not isinstance(paths, tuple): + raise ValueError('paths must be a tuple') + for i, path in enumerate(paths): + with open(path, 'w') as f: + f.write(f'{i}') + + head = b.new_python_job() + head.call(write, (head.ofile1, head.ofile2)) + + tail = b.new_bash_job() + tail.command(f'cat {head.ofile1}') + tail.command(f'cat {head.ofile2}') + + res = b.run() + assert res + assert tail._job_id + res_status = res.status() + assert res_status['state'] == 'success', str((res_status, res.debug_info())) + assert res.get_job_log(tail._job_id)['main'] == '01', str(res.debug_info()) + def test_list_recursive_resource_extraction_in_python_jobs(self): b = self.batch(default_python_image=PYTHON_DILL_IMAGE) diff --git a/hail/scripts/test_requester_pays_parsing.py b/hail/scripts/test_requester_pays_parsing.py index d73f09b30dc..d8c5794d377 100644 --- a/hail/scripts/test_requester_pays_parsing.py +++ b/hail/scripts/test_requester_pays_parsing.py @@ -5,7 +5,7 @@ from hailtop.aiocloud.aiogoogle import get_gcs_requester_pays_configuration from hailtop.aiocloud.aiogoogle.user_config import get_spark_conf_gcs_requester_pays_configuration, spark_conf_path -from hailtop.config.user_config import ConfigVariable, configuration_of +from hailtop.config import ConfigVariable, configuration_of from hailtop.utils.process import check_exec_output if 'YOU_MAY_OVERWRITE_MY_SPARK_DEFAULTS_CONF_AND_HAILCTL_SETTINGS' not in os.environ: From 344b9e3ab4f22c99f5b878206cd07001d0110aea Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 1 Sep 2023 14:25:52 -0400 Subject: [PATCH 167/180] [python-dill][hailtop] update past the bad version of dill (#13536) Fixes https://github.com/hail-is/hail/issues/13535. All the new hailgenetics/dill images are now up: https://hub.docker.com/r/hailgenetics/python-dill/tags --- auth/pinned-requirements.txt | 2 +- batch/pinned-requirements.txt | 9 ++-- ci/pinned-requirements.txt | 4 +- docker/hailgenetics/python-dill/Dockerfile | 2 +- gear/pinned-requirements.txt | 6 +-- hail/python/dev/pinned-requirements.txt | 53 ++++++++++----------- hail/python/hail/expr/types.py | 6 ++- hail/python/hailtop/pinned-requirements.txt | 15 +++--- hail/python/hailtop/requirements.txt | 2 +- hail/python/pinned-requirements.txt | 26 +++++----- hail/python/requirements.txt | 1 - web_common/pinned-requirements.txt | 2 +- 12 files changed, 61 insertions(+), 67 deletions(-) diff --git a/auth/pinned-requirements.txt b/auth/pinned-requirements.txt index 2cfa1041603..a94488a6fe8 100644 --- a/auth/pinned-requirements.txt +++ b/auth/pinned-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/auth/pinned-requirements.txt hail/auth/requirements.txt diff --git a/batch/pinned-requirements.txt b/batch/pinned-requirements.txt index c0570830847..227558f7373 100644 --- a/batch/pinned-requirements.txt +++ b/batch/pinned-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/batch/pinned-requirements.txt hail/batch/requirements.txt @@ -64,7 +64,7 @@ multidict==6.0.4 # -c hail/batch/../web_common/pinned-requirements.txt # aiohttp # yarl -numpy==1.24.4 +numpy==1.25.2 # via # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt @@ -74,11 +74,11 @@ packaging==23.1 # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt # plotly -pandas==2.0.3 +pandas==2.1.0 # via # -c hail/batch/../hail/python/pinned-requirements.txt # -r hail/batch/requirements.txt -plotly==5.16.0 +plotly==5.16.1 # via # -c hail/batch/../hail/python/pinned-requirements.txt # -r hail/batch/requirements.txt @@ -90,7 +90,6 @@ python-dateutil==2.8.2 # pandas pytz==2023.3 # via - # -c hail/batch/../hail/python/dev/pinned-requirements.txt # -c hail/batch/../hail/python/pinned-requirements.txt # pandas six==1.16.0 diff --git a/ci/pinned-requirements.txt b/ci/pinned-requirements.txt index cc00bdd1b73..532617d70fa 100644 --- a/ci/pinned-requirements.txt +++ b/ci/pinned-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/ci/pinned-requirements.txt hail/ci/requirements.txt @@ -22,7 +22,7 @@ charset-normalizer==3.2.0 # -c hail/ci/../hail/python/pinned-requirements.txt # -c hail/ci/../web_common/pinned-requirements.txt # requests -click==8.1.6 +click==8.1.7 # via # -c hail/ci/../gear/pinned-requirements.txt # -c hail/ci/../hail/python/dev/pinned-requirements.txt diff --git a/docker/hailgenetics/python-dill/Dockerfile b/docker/hailgenetics/python-dill/Dockerfile index b474f2d0626..31a2d937b89 100644 --- a/docker/hailgenetics/python-dill/Dockerfile +++ b/docker/hailgenetics/python-dill/Dockerfile @@ -1,6 +1,6 @@ ARG PYTHON_VERSION FROM python:${PYTHON_VERSION} -RUN pip install --upgrade --no-cache-dir dill numpy scipy scikit-learn && \ +RUN pip install --upgrade --no-cache-dir 'dill>=0.3.6' numpy scipy scikit-learn && \ python3 -m pip check && \ apt-get update && \ apt-get install -y \ diff --git a/gear/pinned-requirements.txt b/gear/pinned-requirements.txt index 157e539aa3b..dba5ad239c6 100644 --- a/gear/pinned-requirements.txt +++ b/gear/pinned-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/gear/pinned-requirements.txt hail/gear/requirements.txt @@ -57,7 +57,7 @@ charset-normalizer==3.2.0 # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # requests -click==8.1.6 +click==8.1.7 # via # -c hail/gear/../hail/python/dev/pinned-requirements.txt # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt @@ -129,7 +129,7 @@ multidict==6.0.4 # -c hail/gear/../hail/python/pinned-requirements.txt # aiohttp # yarl -orjson==3.9.4 +orjson==3.9.5 # via # -c hail/gear/../hail/python/hailtop/pinned-requirements.txt # -c hail/gear/../hail/python/pinned-requirements.txt diff --git a/hail/python/dev/pinned-requirements.txt b/hail/python/dev/pinned-requirements.txt index 495e3011ac9..cbb0b924223 100644 --- a/hail/python/dev/pinned-requirements.txt +++ b/hail/python/dev/pinned-requirements.txt @@ -1,12 +1,12 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/hail/python/dev/pinned-requirements.txt hail/hail/python/dev/requirements.txt # alabaster==0.7.13 # via sphinx -anyio==3.7.1 +anyio==4.0.0 # via jupyter-server argon2-cffi==23.1.0 # via jupyter-server @@ -52,7 +52,7 @@ charset-normalizer==3.2.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt # requests -click==8.1.6 +click==8.1.7 # via # -c hail/hail/python/dev/../pinned-requirements.txt # -r hail/hail/python/dev/requirements.txt @@ -92,6 +92,7 @@ docutils==0.18.1 exceptiongroup==1.1.3 # via # anyio + # ipython # pytest execnet==2.0.2 # via pytest-xdist @@ -126,12 +127,7 @@ importlib-metadata==6.8.0 # nbconvert # sphinx importlib-resources==6.0.1 - # via - # jsonschema - # jsonschema-specifications - # jupyterlab - # matplotlib - # notebook + # via matplotlib iniconfig==2.0.0 # via pytest ipykernel==6.25.1 @@ -140,7 +136,7 @@ ipykernel==6.25.1 # jupyter-console # jupyterlab # qtconsole -ipython==8.12.2 +ipython==8.15.0 # via # ipykernel # ipywidgets @@ -201,7 +197,7 @@ jupyter-events==0.7.0 # via jupyter-server jupyter-lsp==2.2.0 # via jupyterlab -jupyter-server==2.7.2 +jupyter-server==2.7.3 # via # jupyter-lsp # jupyterlab @@ -243,7 +239,7 @@ mypy-extensions==1.0.0 # via black nbclient==0.8.0 # via nbconvert -nbconvert==7.7.4 +nbconvert==7.8.0 # via # jupyter # jupyter-server @@ -264,13 +260,13 @@ nodeenv==1.8.0 # via # pre-commit # pyright -notebook==7.0.2 +notebook==7.0.3 # via jupyter notebook-shim==0.2.3 # via # jupyterlab # notebook -numpy==1.24.4 +numpy==1.25.2 # via # -c hail/hail/python/dev/../pinned-requirements.txt # contourpy @@ -308,8 +304,6 @@ pillow==10.0.0 # via # -c hail/hail/python/dev/../pinned-requirements.txt # matplotlib -pkgutil-resolve-name==1.3.10 - # via jsonschema platformdirs==3.10.0 # via # black @@ -352,7 +346,7 @@ pylint==2.17.5 # via -r hail/hail/python/dev/requirements.txt pyparsing==3.0.9 # via matplotlib -pyright==1.1.324 +pyright==1.1.325 # via -r hail/hail/python/dev/requirements.txt pytest==7.4.0 # via @@ -389,10 +383,6 @@ python-json-logger==2.0.7 # via # -c hail/hail/python/dev/../pinned-requirements.txt # jupyter-events -pytz==2023.3 - # via - # -c hail/hail/python/dev/../pinned-requirements.txt - # babel pyyaml==6.0.1 # via # -c hail/hail/python/dev/../pinned-requirements.txt @@ -407,7 +397,7 @@ pyzmq==25.1.1 # qtconsole qtconsole==5.4.3 # via jupyter -qtpy==2.3.1 +qtpy==2.4.0 # via qtconsole referencing==0.30.2 # via @@ -454,17 +444,22 @@ sphinx==6.2.1 # nbsphinx # sphinx-autodoc-typehints # sphinx-rtd-theme + # sphinxcontrib-applehelp + # sphinxcontrib-devhelp + # sphinxcontrib-htmlhelp # sphinxcontrib-jquery # sphinxcontrib-katex + # sphinxcontrib-qthelp + # sphinxcontrib-serializinghtml sphinx-autodoc-typehints==1.23.0 # via -r hail/hail/python/dev/requirements.txt sphinx-rtd-theme==1.3.0 # via -r hail/hail/python/dev/requirements.txt -sphinxcontrib-applehelp==1.0.4 +sphinxcontrib-applehelp==1.0.7 # via sphinx -sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-devhelp==1.0.5 # via sphinx -sphinxcontrib-htmlhelp==2.0.1 +sphinxcontrib-htmlhelp==2.0.4 # via sphinx sphinxcontrib-jquery==4.1 # via sphinx-rtd-theme @@ -472,9 +467,9 @@ sphinxcontrib-jsmath==1.0.1 # via sphinx sphinxcontrib-katex==0.9.7 # via -r hail/hail/python/dev/requirements.txt -sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-qthelp==1.0.6 # via sphinx -sphinxcontrib-serializinghtml==1.1.5 +sphinxcontrib-serializinghtml==1.1.9 # via sphinx stack-data==0.6.2 # via ipython @@ -535,7 +530,7 @@ types-pyyaml==6.0.12.11 # via -r hail/hail/python/dev/requirements.txt types-requests==2.31.0.2 # via -r hail/hail/python/dev/requirements.txt -types-setuptools==68.1.0.0 +types-setuptools==68.1.0.1 # via -r hail/hail/python/dev/requirements.txt types-six==1.16.21.9 # via -r hail/hail/python/dev/requirements.txt @@ -560,7 +555,7 @@ urllib3==1.26.16 # via # -c hail/hail/python/dev/../pinned-requirements.txt # requests -virtualenv==20.24.3 +virtualenv==20.24.4 # via pre-commit wcwidth==0.2.6 # via prompt-toolkit diff --git a/hail/python/hail/expr/types.py b/hail/python/hail/expr/types.py index d7721349c3d..01be10eaa22 100644 --- a/hail/python/hail/expr/types.py +++ b/hail/python/hail/expr/types.py @@ -2138,8 +2138,12 @@ def from_numpy(np_dtype): def dtypes_from_pandas(pd_dtype): if type(pd_dtype) == pd.StringDtype: return hl.tstr - elif pd.api.types.is_int64_dtype(pd_dtype): + elif pd_dtype == np.int64: return hl.tint64 + elif pd_dtype == np.uint64: + # Hail does *not* support unsigned integers but the next condition, + # pd.api.types.is_integer_dtype(pd_dtype) would return true on unsigned 64-bit ints + return None # For some reason pandas doesn't have `is_int32_dtype`, so we use `is_integer_dtype` if first branch failed. elif pd.api.types.is_integer_dtype(pd_dtype): return hl.tint32 diff --git a/hail/python/hailtop/pinned-requirements.txt b/hail/python/hailtop/pinned-requirements.txt index 85c381c8ffd..bdcd36b2cf6 100644 --- a/hail/python/hailtop/pinned-requirements.txt +++ b/hail/python/hailtop/pinned-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/hail/python/hailtop/pinned-requirements.txt hail/hail/python/hailtop/requirements.txt @@ -16,7 +16,7 @@ attrs==23.1.0 # via aiohttp azure-common==1.1.28 # via azure-mgmt-storage -azure-core==1.29.2 +azure-core==1.29.3 # via # azure-identity # azure-mgmt-core @@ -30,9 +30,9 @@ azure-mgmt-storage==20.1.0 # via -r hail/hail/python/hailtop/requirements.txt azure-storage-blob==12.17.0 # via -r hail/hail/python/hailtop/requirements.txt -boto3==1.28.26 +boto3==1.28.39 # via -r hail/hail/python/hailtop/requirements.txt -botocore==1.31.26 +botocore==1.31.39 # via # -r hail/hail/python/hailtop/requirements.txt # boto3 @@ -51,7 +51,7 @@ charset-normalizer==3.2.0 # via # aiohttp # requests -click==8.1.6 +click==8.1.7 # via typer commonmark==0.9.1 # via rich @@ -122,7 +122,7 @@ nest-asyncio==1.5.7 # via -r hail/hail/python/hailtop/requirements.txt oauthlib==3.2.2 # via requests-oauthlib -orjson==3.9.4 +orjson==3.9.5 # via -r hail/hail/python/hailtop/requirements.txt portalocker==2.7.0 # via msal-extensions @@ -165,7 +165,7 @@ rich==12.6.0 # via -r hail/hail/python/hailtop/requirements.txt rsa==4.9 # via google-auth -s3transfer==0.6.1 +s3transfer==0.6.2 # via boto3 six==1.16.0 # via @@ -185,7 +185,6 @@ typing-extensions==4.7.1 # azure-core # azure-storage-blob # janus - # rich # typer urllib3==1.26.16 # via diff --git a/hail/python/hailtop/requirements.txt b/hail/python/hailtop/requirements.txt index 47ac9b6eba7..236cb0d57a7 100644 --- a/hail/python/hailtop/requirements.txt +++ b/hail/python/hailtop/requirements.txt @@ -5,7 +5,7 @@ azure-mgmt-storage==20.1.0 azure-storage-blob>=12.11.0,<13 boto3>=1.17,<2.0 botocore>=1.20,<2.0 -dill>=0.3.1.1,<0.4 +dill>=0.3.6,<0.4 frozenlist>=1.3.1,<2 google-auth>=2.14.1,<3 google-cloud-storage>=1.25.0 diff --git a/hail/python/pinned-requirements.txt b/hail/python/pinned-requirements.txt index a37e5e1985c..1f3dac7fdb3 100644 --- a/hail/python/pinned-requirements.txt +++ b/hail/python/pinned-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/hail/python/pinned-requirements.txt hail/hail/python/requirements.txt @@ -32,7 +32,7 @@ azure-common==1.1.28 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-mgmt-storage -azure-core==1.29.2 +azure-core==1.29.3 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # azure-identity @@ -55,13 +55,13 @@ azure-storage-blob==12.17.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -bokeh==3.1.1 +bokeh==3.2.2 # via -r hail/hail/python/requirements.txt -boto3==1.28.26 +boto3==1.28.39 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -botocore==1.31.26 +botocore==1.31.39 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -86,7 +86,7 @@ charset-normalizer==3.2.0 # -c hail/hail/python/hailtop/pinned-requirements.txt # aiohttp # requests -click==8.1.6 +click==8.1.7 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # typer @@ -111,7 +111,6 @@ dill==0.3.7 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt - # -r hail/hail/python/requirements.txt frozenlist==1.4.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt @@ -204,7 +203,7 @@ nest-asyncio==1.5.7 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt -numpy==1.24.4 +numpy==1.25.2 # via # -r hail/hail/python/requirements.txt # bokeh @@ -215,7 +214,7 @@ oauthlib==3.2.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # requests-oauthlib -orjson==3.9.4 +orjson==3.9.5 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt @@ -223,7 +222,7 @@ packaging==23.1 # via # bokeh # plotly -pandas==2.0.3 +pandas==2.1.0 # via # -r hail/hail/python/requirements.txt # bokeh @@ -231,7 +230,7 @@ parsimonious==0.10.0 # via -r hail/hail/python/requirements.txt pillow==10.0.0 # via bokeh -plotly==5.16.0 +plotly==5.16.1 # via -r hail/hail/python/requirements.txt portalocker==2.7.0 # via @@ -271,7 +270,7 @@ pyjwt[crypto]==2.8.0 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # msal -pyspark==3.3.2 +pyspark==3.3.3 # via -r hail/hail/python/requirements.txt python-dateutil==2.8.2 # via @@ -313,7 +312,7 @@ rsa==4.9 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # google-auth -s3transfer==0.6.1 +s3transfer==0.6.2 # via # -c hail/hail/python/hailtop/pinned-requirements.txt # boto3 @@ -349,7 +348,6 @@ typing-extensions==4.7.1 # azure-core # azure-storage-blob # janus - # rich # typer tzdata==2023.3 # via pandas diff --git a/hail/python/requirements.txt b/hail/python/requirements.txt index 0674fefa847..71be0275ec4 100644 --- a/hail/python/requirements.txt +++ b/hail/python/requirements.txt @@ -6,7 +6,6 @@ avro>=1.10,<1.12 bokeh>=3,<4 decorator<5 Deprecated>=1.2.10,<1.3 -dill>=0.3.1.1,<0.4 frozenlist>=1.3.1,<2 numpy<2 pandas>=2,<3 diff --git a/web_common/pinned-requirements.txt b/web_common/pinned-requirements.txt index abdd6465451..c09fd93d02c 100644 --- a/web_common/pinned-requirements.txt +++ b/web_common/pinned-requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # pip-compile --output-file=hail/web_common/pinned-requirements.txt hail/web_common/requirements.txt From 5205d61bec759f09b33166a6b4db972fd896f6ff Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 1 Sep 2023 15:57:56 -0400 Subject: [PATCH 168/180] [pre-commit] add ruff, check-sql checks (#13474) We can use this for pyright or mypy but I found both took ~1.5s even on a tiny file like `ci.py`. The check is slow the first time because it has to install a new venv; however, subsequent executions can use the extant venv. --- .pre-commit-config.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ef9806b31b9..88d5a94de29 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,6 +3,12 @@ default_install_hook_types: [pre-commit, pre-push] repos: - repo: local hooks: + - id: ruff + name: ruff + entry: ruff --fix --show-fixes + language: system + types: [python] + require_serial: true - id: pyright name: pyright entry: pyright From 2342d1b4e2094a37dc01e2afce1db2c96567cde8 Mon Sep 17 00:00:00 2001 From: sjparsa <66189052+sjparsa@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:12:12 -0400 Subject: [PATCH 169/180] [batch] update ubuntu image version to latest (#13440) Upgrade to Ubuntu 22.04 everywhere including for the Batch Worker VMs in Azure and Google. --------- Co-authored-by: Sophie Parsa Co-authored-by: Daniel Goldstein --- batch/Dockerfile.worker | 7 ++-- batch/az-create-worker-image.sh | 8 ++--- .../cloud/azure/driver/create_instance.py | 4 +-- batch/batch/cloud/azure/worker/worker_api.py | 3 +- .../batch/cloud/gcp/driver/create_instance.py | 3 +- batch/gcp-create-worker-image.sh | 4 +-- batch/test/test_batch.py | 2 +- batch/test/utils.py | 2 +- benchmark/Makefile | 2 +- build.yaml | 2 +- docker/hail-ubuntu/Dockerfile | 6 ++-- docker/third-party/images.txt | 2 +- hail/python/hailtop/batch/backend.py | 2 +- .../hailtop/batch/docs/cookbook/clumping.rst | 4 +-- .../docs/cookbook/files/batch_clumping.py | 2 +- .../hailtop/batch/docs/docker_resources.rst | 6 ++-- hail/python/hailtop/batch/job.py | 4 +-- hail/python/test/hailtop/batch/test_batch.py | 2 +- .../batch_client/BatchClientSuite.scala | 2 +- infra/azure/modules/batch/main.tf | 17 ++++++++++ infra/azure/modules/vdc/main.tf | 32 ++----------------- infra/gcp-broad/main.tf | 2 +- infra/gcp/README.md | 2 +- infra/gcp/main.tf | 2 +- infra/k8s/global_config/main.tf | 2 +- ukbb-rg/Dockerfile.browser | 2 +- ukbb-rg/Dockerfile.static | 2 +- 27 files changed, 61 insertions(+), 67 deletions(-) diff --git a/batch/Dockerfile.worker b/batch/Dockerfile.worker index 561df7a409c..1fd1f205f40 100644 --- a/batch/Dockerfile.worker +++ b/batch/Dockerfile.worker @@ -20,12 +20,15 @@ RUN echo "APT::Acquire::Retries \"5\";" > /etc/apt/apt.conf.d/80-retries && \ hail-apt-get-install fuse gcsfuse=0.41.12 {% elif global.cloud == "azure" %} +RUN apt-get update && \ + hail-apt-get-install libreadline8 + # https://github.com/Azure/azure-storage-fuse/issues/603 RUN hail-apt-get-install ca-certificates pkg-config libfuse-dev cmake libcurl4-gnutls-dev libgnutls28-dev uuid-dev libgcrypt20-dev && \ - curl -LO https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb && \ + curl -LO https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb && \ dpkg -i packages-microsoft-prod.deb && \ apt-get update && \ - hail-apt-get-install blobfuse + hail-apt-get-install blobfuse2 {% else %} RUN echo "!!! UNEXPECTED CLOUD {{global.cloud}} !!!" && exit 1 diff --git a/batch/az-create-worker-image.sh b/batch/az-create-worker-image.sh index e523c4dfe49..8e0b52bd5cb 100755 --- a/batch/az-create-worker-image.sh +++ b/batch/az-create-worker-image.sh @@ -15,7 +15,7 @@ popd SHARED_GALLERY_NAME="${RESOURCE_GROUP}_batch" BUILD_IMAGE_RESOURCE_GROUP="${RESOURCE_GROUP}-build-batch-worker-image" VM_NAME=build-batch-worker-image -WORKER_VERSION=0.0.12 +WORKER_VERSION=0.0.13 USERNAME=$(whoami) @@ -45,7 +45,7 @@ echo "Creating $VM_NAME VM..." IP=$(az vm create \ --resource-group $BUILD_IMAGE_RESOURCE_GROUP \ --name $VM_NAME \ - --image UbuntuLTS \ + --image Ubuntu2204 \ --generate-ssh-keys \ --public-ip-sku Standard \ --assign-identity ${BATCH_WORKER_IDENTITY} \ @@ -81,7 +81,7 @@ az vm generalize \ --name $VM_NAME az sig image-version delete \ - --gallery-image-definition batch-worker \ + --gallery-image-definition batch-worker-22-04 \ --gallery-name ${SHARED_GALLERY_NAME} \ --resource-group ${RESOURCE_GROUP} \ --gallery-image-version ${WORKER_VERSION} || true @@ -91,7 +91,7 @@ echo "Creating image..." az sig image-version create \ --resource-group ${RESOURCE_GROUP} \ --gallery-name ${SHARED_GALLERY_NAME} \ - --gallery-image-definition batch-worker \ + --gallery-image-definition batch-worker-22-04 \ --gallery-image-version ${WORKER_VERSION} \ --target-regions ${LOCATION} \ --replica-count 1 \ diff --git a/batch/batch/cloud/azure/driver/create_instance.py b/batch/batch/cloud/azure/driver/create_instance.py index b820287cb03..ceffb1c1720 100644 --- a/batch/batch/cloud/azure/driver/create_instance.py +++ b/batch/batch/cloud/azure/driver/create_instance.py @@ -272,7 +272,6 @@ def create_vm_config( -v /var/run/docker.sock:/var/run/docker.sock \ -v /var/run/netns:/var/run/netns:shared \ -v /usr/bin/docker:/usr/bin/docker \ --v /usr/sbin/xfs_quota:/usr/sbin/xfs_quota \ -v /batch:/batch:shared \ -v /logs:/logs \ -v /global-config:/global-config \ @@ -290,6 +289,7 @@ def create_vm_config( --cap-add SYS_ADMIN \ --security-opt apparmor:unconfined \ --network host \ +--cgroupns host \ $BATCH_WORKER_IMAGE \ python3 -u -m batch.worker.worker >worker.log 2>&1 @@ -427,7 +427,7 @@ def create_vm_config( 'imageReference': { 'value': { 'id': f'/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/' - f'Microsoft.Compute/galleries/{resource_group}_batch/images/batch-worker/versions/0.0.12' + f'Microsoft.Compute/galleries/{resource_group}_batch/images/batch-worker-22-04/versions/0.0.13' } }, 'workspaceName': { diff --git a/batch/batch/cloud/azure/worker/worker_api.py b/batch/batch/cloud/azure/worker/worker_api.py index 0f035fe888a..6e65d97dc3f 100644 --- a/batch/batch/cloud/azure/worker/worker_api.py +++ b/batch/batch/cloud/azure/worker/worker_api.py @@ -92,7 +92,8 @@ async def _mount_cloudfuse( options.append('ro') await check_exec_output( - 'blobfuse', + 'blobfuse2', + 'mountv1', mount_base_path_data, f'--tmp-path={mount_base_path_tmp}', f'--config-file={fuse_credentials_path}', diff --git a/batch/batch/cloud/gcp/driver/create_instance.py b/batch/batch/cloud/gcp/driver/create_instance.py index dc2a8ff164a..374bf0d7272 100644 --- a/batch/batch/cloud/gcp/driver/create_instance.py +++ b/batch/batch/cloud/gcp/driver/create_instance.py @@ -128,7 +128,7 @@ def scheduling() -> dict: 'boot': True, 'autoDelete': True, 'initializeParams': { - 'sourceImage': f'projects/{project}/global/images/batch-worker-12', + 'sourceImage': f'projects/{project}/global/images/batch-worker-13', 'diskType': f'projects/{project}/zones/{zone}/diskTypes/pd-ssd', 'diskSizeGb': str(boot_disk_size_gb), }, @@ -380,6 +380,7 @@ def scheduling() -> dict: --cap-add SYS_ADMIN \ --security-opt apparmor:unconfined \ --network host \ +--cgroupns host \ $BATCH_WORKER_IMAGE \ python3 -u -m batch.worker.worker >worker.log 2>&1 diff --git a/batch/gcp-create-worker-image.sh b/batch/gcp-create-worker-image.sh index 5226a5e73e9..c649d9cec09 100755 --- a/batch/gcp-create-worker-image.sh +++ b/batch/gcp-create-worker-image.sh @@ -14,7 +14,7 @@ PROJECT=$(get_global_config_field gcp_project $NAMESPACE) ZONE=$(get_global_config_field gcp_zone $NAMESPACE) DOCKER_ROOT_IMAGE=$(get_global_config_field docker_root_image $NAMESPACE) -WORKER_IMAGE_VERSION=12 +WORKER_IMAGE_VERSION=13 if [ "$NAMESPACE" == "default" ]; then WORKER_IMAGE=batch-worker-${WORKER_IMAGE_VERSION} @@ -24,7 +24,7 @@ else BUILDER=build-batch-worker-$NAMESPACE-image fi -UBUNTU_IMAGE=ubuntu-minimal-2004-focal-v20230725 +UBUNTU_IMAGE=ubuntu-minimal-2204-jammy-v20230726 create_build_image_instance() { gcloud -q compute --project ${PROJECT} instances delete \ diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 3cd0fabc404..548a5532748 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -1111,7 +1111,7 @@ def test_verify_no_access_to_metadata_server(client: BatchClient): status = j.wait() assert status['state'] == 'Failed', str((status, b.debug_info())) job_log = j.log() - assert "Connection timed out" in job_log['main'], str((job_log, b.debug_info())) + assert "Connection timeout" in job_log['main'], str((job_log, b.debug_info())) def test_submit_batch_in_job(client: BatchClient, remote_tmpdir: str): diff --git a/batch/test/utils.py b/batch/test/utils.py index 7dc7d832020..a41350dab69 100644 --- a/batch/test/utils.py +++ b/batch/test/utils.py @@ -6,7 +6,7 @@ import hailtop.batch_client.client as bc from hailtop import pip_version -DOCKER_ROOT_IMAGE = os.environ.get('DOCKER_ROOT_IMAGE', 'ubuntu:20.04') +DOCKER_ROOT_IMAGE = os.environ.get('DOCKER_ROOT_IMAGE', 'ubuntu:22.04') HAIL_GENETICS_HAIL_IMAGE = os.environ.get('HAIL_GENETICS_HAIL_IMAGE', f'hailgenetics/hail:{pip_version()}') diff --git a/benchmark/Makefile b/benchmark/Makefile index 8cf345563d5..5c9d2dc5333 100644 --- a/benchmark/Makefile +++ b/benchmark/Makefile @@ -31,7 +31,7 @@ cleanup_image: BENCHMARK_DOCKER_TAG ?= $(shell whoami) BECNHMARK_IMAGE_REPOSITORY ?= us-docker.pkg.dev/broad-ctsa/hail-benchmarks BENCHMARK_REPO_BASE = $(BECNHMARK_IMAGE_REPOSITORY)/$(BENCHMARK_DOCKER_TAG) -DOCKER_ROOT_IMAGE := ubuntu:20.04 +DOCKER_ROOT_IMAGE := ubuntu:22.04 ifndef HAIL_WHEEL image_sha: diff --git a/build.yaml b/build.yaml index dc450e0d20a..b9a9a35aa48 100644 --- a/build.yaml +++ b/build.yaml @@ -2778,7 +2778,7 @@ steps: --from-literal=github_context="ci-test" \ --from-literal=storage_uri="{{ global.test_storage_uri }}" \ --from-literal=deploy_steps="[]" \ - --from-literal=watched_branches="[[\"hail-ci-test/ci-test-{{create_ci_test_repo.token}}:master\", true, true]]" \ + --from-literal=watched_branches="[[\"hail-ci-test/ci-test-{{create_ci_test_repo.token}}:main\", true, true]]" \ --save-config --dry-run=client -o yaml \ | kubectl -n {{ default_ns.name }} apply -f - serviceAccount: diff --git a/docker/hail-ubuntu/Dockerfile b/docker/hail-ubuntu/Dockerfile index fd5abeed626..98add642508 100644 --- a/docker/hail-ubuntu/Dockerfile +++ b/docker/hail-ubuntu/Dockerfile @@ -1,4 +1,4 @@ -FROM {{ global.docker_prefix }}/ubuntu:focal-20221019 +FROM {{ global.docker_prefix }}/ubuntu:jammy-20230624 ENV LANG C.UTF-8 ENV DEBIAN_FRONTEND noninteractive COPY retry /bin/retry @@ -16,9 +16,9 @@ RUN chmod 755 /bin/retry && \ hail-apt-get-install curl gpg jq rsync && \ curl 'https://keyserver.ubuntu.com/pks/lookup?search=0xF23C5A6CF475977595C89F51BA6932366A755776&hash=on&exact=on&options=mr&op=get' \ | gpg --dearmor > /usr/share/keyrings/deadsnakes-ppa-archive-keyring.gpg && \ - echo 'deb [signed-by=/usr/share/keyrings/deadsnakes-ppa-archive-keyring.gpg] http://ppa.launchpad.net/deadsnakes/ppa/ubuntu focal main' \ + echo 'deb [signed-by=/usr/share/keyrings/deadsnakes-ppa-archive-keyring.gpg] http://ppa.launchpad.net/deadsnakes/ppa/ubuntu jammy main' \ >> /etc/apt/sources.list && \ - echo 'deb-src [signed-by=/usr/share/keyrings/deadsnakes-ppa-archive-keyring.gpg] http://ppa.launchpad.net/deadsnakes/ppa/ubuntu focal main' \ + echo 'deb-src [signed-by=/usr/share/keyrings/deadsnakes-ppa-archive-keyring.gpg] http://ppa.launchpad.net/deadsnakes/ppa/ubuntu jammy main' \ >> /etc/apt/sources.list && \ hail-apt-get-install python3.9-minimal python3.9-dev python3.9-distutils gcc g++ && \ update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 && \ diff --git a/docker/third-party/images.txt b/docker/third-party/images.txt index 1f1dfdbf40c..6a0b9811481 100644 --- a/docker/third-party/images.txt +++ b/docker/third-party/images.txt @@ -13,6 +13,6 @@ python:3.10-slim redis:6.0.6-alpine ubuntu:18.04 ubuntu:19.04 -ubuntu:20.04 +ubuntu:22.04 ubuntu:bionic-20200921 ubuntu:focal-20221019 diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index 13d0111a0d7..48886d7a115 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -581,7 +581,7 @@ async def _async_run(self, batch_remote_tmpdir = f'{self.remote_tmpdir}{uid}' local_tmpdir = f'/io/batch/{uid}' - default_image = 'ubuntu:20.04' + default_image = 'ubuntu:22.04' attributes = copy.deepcopy(batch.attributes) if batch.name is not None: diff --git a/hail/python/hailtop/batch/docs/cookbook/clumping.rst b/hail/python/hailtop/batch/docs/cookbook/clumping.rst index db34d54d11d..9a57c0ffd3d 100644 --- a/hail/python/hailtop/batch/docs/cookbook/clumping.rst +++ b/hail/python/hailtop/batch/docs/cookbook/clumping.rst @@ -210,7 +210,7 @@ Merge Clumping Results The third function concatenates all of the clumping results per chromosome into a single file with one header line. The inputs are the :class:`.Batch` for which to create a new :class:`.BashJob` -and a list containing all of the individual clumping results files. We use the ``ubuntu:20.04`` +and a list containing all of the individual clumping results files. We use the ``ubuntu:22.04`` Docker image for this job. The return value is the new :class:`.BashJob` created. .. code-block:: python @@ -220,7 +220,7 @@ Docker image for this job. The return value is the new :class:`.BashJob` created Merge clumped results files together """ merger = batch.new_job(name='merge-results') - merger.image('ubuntu:20.04') + merger.image('ubuntu:22.04') if results: merger.command(f''' head -n 1 {results[0]} > {merger.ofile} diff --git a/hail/python/hailtop/batch/docs/cookbook/files/batch_clumping.py b/hail/python/hailtop/batch/docs/cookbook/files/batch_clumping.py index f3e0bb4eddf..eec7c9a0f24 100644 --- a/hail/python/hailtop/batch/docs/cookbook/files/batch_clumping.py +++ b/hail/python/hailtop/batch/docs/cookbook/files/batch_clumping.py @@ -52,7 +52,7 @@ def merge(batch, results): Merge clumped results files together """ merger = batch.new_job(name='merge-results') - merger.image('ubuntu:20.04') + merger.image('ubuntu:22.04') if results: merger.command(f''' head -n 1 {results[0]} > {merger.ofile} diff --git a/hail/python/hailtop/batch/docs/docker_resources.rst b/hail/python/hailtop/batch/docs/docker_resources.rst index a7573aed938..42df0db1781 100644 --- a/hail/python/hailtop/batch/docs/docker_resources.rst +++ b/hail/python/hailtop/batch/docs/docker_resources.rst @@ -24,13 +24,13 @@ Creating a Dockerfile A Dockerfile contains the instructions for creating an image and is typically called `Dockerfile`. The first directive at the top of each Dockerfile is `FROM` which states what image to create this -image on top of. For example, we can build off of `ubuntu:20.04` which contains a complete Ubuntu +image on top of. For example, we can build off of `ubuntu:22.04` which contains a complete Ubuntu operating system, but does not have Python installed by default. You can use any image that already exists to base your image on. An image that has Python preinstalled is `python:3.6-slim-stretch` and one that has `gcloud` installed is `google/cloud-sdk:slim`. Be careful when choosing images from unknown sources! -In the example below, we create a Dockerfile that is based on `ubuntu:20.04`. In this file, we show an +In the example below, we create a Dockerfile that is based on `ubuntu:22.04`. In this file, we show an example of installing PLINK in the image with the `RUN` directive, which is an arbitrary bash command. First, we download a bunch of utilities that do not come with Ubuntu using `apt-get`. Next, we download and install PLINK from source. Finally, we can copy files from your local computer to the @@ -39,7 +39,7 @@ docker image using the `COPY` directive. .. code-block:: text - FROM 'ubuntu:20.04' + FROM 'ubuntu:22.04' RUN apt-get update && apt-get install -y \ python3 \ diff --git a/hail/python/hailtop/batch/job.py b/hail/python/hailtop/batch/job.py index a38be18c58b..99c0049bc9e 100644 --- a/hail/python/hailtop/batch/job.py +++ b/hail/python/hailtop/batch/job.py @@ -746,11 +746,11 @@ def image(self, image: str) -> 'BashJob': Examples -------- - Set the job's docker image to `ubuntu:20.04`: + Set the job's docker image to `ubuntu:22.04`: >>> b = Batch() >>> j = b.new_job() - >>> (j.image('ubuntu:20.04') + >>> (j.image('ubuntu:22.04') ... .command(f'echo "hello"')) >>> b.run() # doctest: +SKIP diff --git a/hail/python/test/hailtop/batch/test_batch.py b/hail/python/test/hailtop/batch/test_batch.py index efcc88d9d97..25916667e28 100644 --- a/hail/python/test/hailtop/batch/test_batch.py +++ b/hail/python/test/hailtop/batch/test_batch.py @@ -29,7 +29,7 @@ from hailtop.config.variables import ConfigVariable -DOCKER_ROOT_IMAGE = os.environ.get('DOCKER_ROOT_IMAGE', 'ubuntu:20.04') +DOCKER_ROOT_IMAGE = os.environ.get('DOCKER_ROOT_IMAGE', 'ubuntu:22.04') PYTHON_DILL_IMAGE = 'hailgenetics/python-dill:3.9-slim' HAIL_GENETICS_HAIL_IMAGE = os.environ.get('HAIL_GENETICS_HAIL_IMAGE', f'hailgenetics/hail:{pip_version()}') diff --git a/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala b/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala index 6f333fef074..ca89e8a7498 100644 --- a/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala +++ b/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala @@ -22,7 +22,7 @@ class BatchClientSuite extends TestNGSuite { "job_id" -> JInt(0), "parent_ids" -> JArray(List()), "process" -> JObject( - "image" -> JString("ubuntu:20.04"), + "image" -> JString("ubuntu:22.04"), "command" -> JArray(List( JString("/bin/bash"), JString("-c"), diff --git a/infra/azure/modules/batch/main.tf b/infra/azure/modules/batch/main.tf index 5e6245ecefb..9d0a807da32 100644 --- a/infra/azure/modules/batch/main.tf +++ b/infra/azure/modules/batch/main.tf @@ -39,6 +39,23 @@ resource "azurerm_shared_image" "batch_worker" { } } +resource "azurerm_shared_image" "batch_worker_22_04" { + name = "batch-worker-22-04" + gallery_name = azurerm_shared_image_gallery.batch.name + resource_group_name = var.resource_group.name + location = var.resource_group.location + os_type = "Linux" + specialized = false + + hyper_v_generation = "V2" + + identifier { + publisher = "Hail" + offer = "BatchWorker" + sku = "Ubuntu-22.04-LTS" + } +} + resource "kubernetes_secret" "batch_worker_ssh_public_key" { metadata { name = "batch-worker-ssh-public-key" diff --git a/infra/azure/modules/vdc/main.tf b/infra/azure/modules/vdc/main.tf index 16ee2e3bc4f..3b3537b0de4 100644 --- a/infra/azure/modules/vdc/main.tf +++ b/infra/azure/modules/vdc/main.tf @@ -50,6 +50,8 @@ resource "azurerm_kubernetes_cluster" "vdc" { location = var.resource_group.location dns_prefix = "example" + automatic_channel_upgrade = "stable" + default_node_pool { name = "nonpreempt" vm_size = var.k8s_default_node_pool_machine_type @@ -157,33 +159,3 @@ resource "azurerm_public_ip" "gateway_ip" { sku = "Standard" allocation_method = "Static" } - -resource "kubernetes_pod_disruption_budget" "kube_dns_pdb" { - metadata { - name = "kube-dns" - namespace = "kube-system" - } - spec { - max_unavailable = "1" - selector { - match_labels = { - k8s-app = "kube-dns" - } - } - } -} - -resource "kubernetes_pod_disruption_budget" "kube_dns_autoscaler_pdb" { - metadata { - name = "kube-dns-autoscaler" - namespace = "kube-system" - } - spec { - max_unavailable = "1" - selector { - match_labels = { - k8s-app = "kube-dns-autoscaler" - } - } - } -} diff --git a/infra/gcp-broad/main.tf b/infra/gcp-broad/main.tf index 286addc6b68..573f33239a1 100644 --- a/infra/gcp-broad/main.tf +++ b/infra/gcp-broad/main.tf @@ -57,7 +57,7 @@ locals { "${var.gcp_region}-docker.pkg.dev/${var.gcp_project}/hail" : "gcr.io/${var.gcp_project}" ) - docker_root_image = "${local.docker_prefix}/ubuntu:20.04" + docker_root_image = "${local.docker_prefix}/ubuntu:22.04" } provider "google" { diff --git a/infra/gcp/README.md b/infra/gcp/README.md index 69930f5a010..4511596ec3a 100644 --- a/infra/gcp/README.md +++ b/infra/gcp/README.md @@ -204,7 +204,7 @@ Instructions: You can now install Hail: - Create a VM on the internal network, standard-8, 100GB PD-SSD, - Ubuntu 20.04 TLS, allow full access to all Cloud APIs, use the + Ubuntu 22.04 TLS, allow full access to all Cloud APIs, use the Terraform service account. 10GB will run out of space. We assume the rest of the commands are run on the VM. You will need to connect to this instance with ssh. You may want to add a suiteable diff --git a/infra/gcp/main.tf b/infra/gcp/main.tf index 4629cd550ed..2a95a96e718 100644 --- a/infra/gcp/main.tf +++ b/infra/gcp/main.tf @@ -54,7 +54,7 @@ locals { "${var.gcp_region}-docker.pkg.dev/${var.gcp_project}/hail" : "gcr.io/${var.gcp_project}" ) - docker_root_image = "${local.docker_prefix}/ubuntu:20.04" + docker_root_image = "${local.docker_prefix}/ubuntu:22.04" } data "sops_file" "terraform_sa_key_sops" { diff --git a/infra/k8s/global_config/main.tf b/infra/k8s/global_config/main.tf index ec6df4d35b1..0cb68237093 100644 --- a/infra/k8s/global_config/main.tf +++ b/infra/k8s/global_config/main.tf @@ -21,7 +21,7 @@ resource "kubernetes_secret" "global_config" { cloud = var.cloud default_namespace = "default" docker_prefix = var.docker_prefix - docker_root_image = "${var.docker_prefix}/ubuntu:20.04" + docker_root_image = "${var.docker_prefix}/ubuntu:22.04" domain = var.domain organization_domain = var.organization_domain internal_ip = var.internal_gateway_ip diff --git a/ukbb-rg/Dockerfile.browser b/ukbb-rg/Dockerfile.browser index 418ec298261..9f8af64b1cb 100644 --- a/ukbb-rg/Dockerfile.browser +++ b/ukbb-rg/Dockerfile.browser @@ -1,4 +1,4 @@ -FROM {{ docker_prefix }}/ubuntu:20.04 +FROM {{ docker_prefix }}/ubuntu:22.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ diff --git a/ukbb-rg/Dockerfile.static b/ukbb-rg/Dockerfile.static index 893fa28ced6..c143b64f6e3 100644 --- a/ukbb-rg/Dockerfile.static +++ b/ukbb-rg/Dockerfile.static @@ -1,4 +1,4 @@ -FROM {{ docker_prefix }}/ubuntu:20.04 +FROM {{ docker_prefix }}/ubuntu:22.04 RUN apt-get update -y && \ apt-get install -y nginx && \ From adc34d39a8b1e8d269a89327e318588fd526da0a Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 1 Sep 2023 18:36:39 -0400 Subject: [PATCH 170/180] [docker] copy even if the tag already exists (#13538) This inspect command prevents us from updating a tag, for example, if we need to replace an image with a security problem or if there is a bug like the one fixed by https://github.com/hail-is/hail/pull/13536. --- docker/hailgenetics/mirror_images.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docker/hailgenetics/mirror_images.sh b/docker/hailgenetics/mirror_images.sh index dae12226d4e..fa1b2b3c6ab 100755 --- a/docker/hailgenetics/mirror_images.sh +++ b/docker/hailgenetics/mirror_images.sh @@ -10,11 +10,8 @@ copy_if_not_present() { if ! skopeo inspect "docker://docker.io/$1"; then echo "$1 does not exist yet, doing nothing" - elif skopeo inspect "docker://$2"; - then - echo "$2 already exists, doing nothing" else - echo "$2 does not exist, copying $1 to $2" + echo "copying $1 to $2" copy_image $1 $2 fi } From f063e96b6b65ae7034331544d73dd4e95f6e2d42 Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 1 Sep 2023 19:43:15 -0400 Subject: [PATCH 171/180] [batch] fix misnamed resources (#13539) I am having trouble determining the effect of this mistake, but it seems like we would be substantially undercharging for the serivce fee if it was really being charged by worker_fraction_in_1024ths instead of core-hours. --- batch/batch/cloud/gcp/instance_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/batch/batch/cloud/gcp/instance_config.py b/batch/batch/cloud/gcp/instance_config.py index 4a74aaf34a7..f4a3340cc64 100644 --- a/batch/batch/cloud/gcp/instance_config.py +++ b/batch/batch/cloud/gcp/instance_config.py @@ -149,8 +149,8 @@ def from_dict(data: dict) -> 'GCPSlimInstanceConfig': GCPStaticSizedDiskResource('disk/pd-ssd/1', boot_disk_size_gb), data_disk_resource, GCPDynamicSizedDiskResource('disk/pd-ssd/1'), - GCPIPFeeResource('service-fee/1'), - GCPServiceFeeResource('ip-fee/1024/1'), + GCPServiceFeeResource('service-fee/1'), + GCPIPFeeResource('ip-fee/1024/1'), ] else: resources = [gcp_resource_from_dict(data) for data in resources] From 799ae7db13fb00bdf3724df7ad40a1437e697b9f Mon Sep 17 00:00:00 2001 From: Dan King Date: Fri, 1 Sep 2023 20:57:39 -0400 Subject: [PATCH 172/180] [fs] fix bugs in glob and list in our GSFS (#13434) CHANGELOG: In QoB, Hail's file systems now correctly list all files in a directory, not just the first 1000. This could manifest in an import_table or import_vcf which used a glob expression. In such a case, only the first 1000 files would have been included in the resulting Table or MatrixTable. I also moved two GSFS-only tests into the FSSuite. There should be very few tests that are cloud-specific. --- .../scala/is/hail/io/fs/GoogleStorageFS.scala | 2 +- hail/src/test/scala/is/hail/fs/FSSuite.scala | 53 ++++++++++++++++--- .../hail/fs/azure/AzureStorageFSSuite.scala | 10 +--- .../is/hail/fs/gs/GoogleStorageFSSuite.scala | 40 +------------- 4 files changed, 49 insertions(+), 56 deletions(-) diff --git a/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala b/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala index 62ef5d3506c..793a43ce559 100644 --- a/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala +++ b/hail/src/main/scala/is/hail/io/fs/GoogleStorageFS.scala @@ -466,7 +466,7 @@ class GoogleStorageFS( ) } - blobs.getValues.iterator.asScala + blobs.iterateAll().iterator.asScala .filter(b => b.getName != path) // elide directory markers created by Hadoop .map(b => GoogleStorageFileStatus(b)) .toArray diff --git a/hail/src/test/scala/is/hail/fs/FSSuite.scala b/hail/src/test/scala/is/hail/fs/FSSuite.scala index 2ae121704ec..628c4981762 100644 --- a/hail/src/test/scala/is/hail/fs/FSSuite.scala +++ b/hail/src/test/scala/is/hail/fs/FSSuite.scala @@ -13,13 +13,13 @@ import org.scalatest.testng.TestNGSuite import org.testng.annotations.Test trait FSSuite extends TestNGSuite { - def root: String + val root: String = System.getenv("HAIL_TEST_STORAGE_URI") - def fsResourcesRoot: String + def fsResourcesRoot: String = System.getenv("HAIL_FS_TEST_CLOUD_RESOURCES_URI") - def fs: FS + def tmpdir: String = System.getenv("HAIL_TEST_STORAGE_URI") - def tmpdir: String + def fs: FS /* Structure of src/test/resources/fs: /a @@ -396,12 +396,51 @@ trait FSSuite extends TestNGSuite { } } } + + @Test def largeDirectoryOperations(): Unit = { + val prefix = s"$tmpdir/fs-suite/delete-many-files/${ java.util.UUID.randomUUID() }" + for (i <- 0 until 2000) { + fs.touch(s"$prefix/$i.suffix") + } + + assert(fs.listStatus(prefix).size == 2000) + assert(fs.glob(prefix + "/" + "*.suffix").size == 2000) + + assert(fs.exists(prefix)) + fs.delete(prefix, recursive = true) + if (fs.exists(prefix)) { + // NB: TestNGSuite.assert does not have a lazy message argument so we must use an if to protect this list + // + // see: https://www.scalatest.org/scaladoc/1.7.2/org/scalatest/testng/TestNGSuite.html + assert(false, s"files not deleted:\n${ fs.listStatus(prefix).map(_.getPath).mkString("\n") }") + } + } + + @Test def testSeekAfterEOF(): Unit = { + val prefix = s"$tmpdir/fs-suite/delete-many-files/${ java.util.UUID.randomUUID() }" + val p = s"$prefix/seek_file" + using(fs.createCachedNoCompression(p)) { os => + os.write(1.toByte) + os.write(2.toByte) + os.write(3.toByte) + os.write(4.toByte) + } + + using(fs.openNoCompression(p)) { is => + assert(is.read() == 1.toByte) + is.seek(3) + assert(is.read() == 4.toByte) + assert(is.read() == (-1).toByte) + is.seek(0) + assert(is.read() == 1.toByte) + } + } } class HadoopFSSuite extends HailSuite with FSSuite { - val root: String = "file:/" + override val root: String = "file:/" - lazy val fsResourcesRoot: String = "file:" + new java.io.File("./src/test/resources/fs").getCanonicalPath + override lazy val fsResourcesRoot: String = "file:" + new java.io.File("./src/test/resources/fs").getCanonicalPath - lazy val tmpdir: String = ctx.tmpdir + override lazy val tmpdir: String = ctx.tmpdir } diff --git a/hail/src/test/scala/is/hail/fs/azure/AzureStorageFSSuite.scala b/hail/src/test/scala/is/hail/fs/azure/AzureStorageFSSuite.scala index fc917fc2c91..4dfde3a4111 100644 --- a/hail/src/test/scala/is/hail/fs/azure/AzureStorageFSSuite.scala +++ b/hail/src/test/scala/is/hail/fs/azure/AzureStorageFSSuite.scala @@ -16,19 +16,11 @@ class AzureStorageFSSuite extends TestNGSuite with FSSuite { if (System.getenv("HAIL_CLOUD") != "azure") { throw new SkipException("This test suite is only run in Azure."); } else { - assert(hail_test_storage_uri != null) + assert(root != null) assert(fsResourcesRoot != null) } } - val hail_test_storage_uri: String = System.getenv("HAIL_TEST_STORAGE_URI") - - val root: String = hail_test_storage_uri - - val fsResourcesRoot: String = System.getenv("HAIL_FS_TEST_CLOUD_RESOURCES_URI") - - lazy val tmpdir: String = hail_test_storage_uri - lazy val fs = { val aac = System.getenv("AZURE_APPLICATION_CREDENTIALS") if (aac == null) { diff --git a/hail/src/test/scala/is/hail/fs/gs/GoogleStorageFSSuite.scala b/hail/src/test/scala/is/hail/fs/gs/GoogleStorageFSSuite.scala index 49600b71bc0..7ab7d9ed27a 100644 --- a/hail/src/test/scala/is/hail/fs/gs/GoogleStorageFSSuite.scala +++ b/hail/src/test/scala/is/hail/fs/gs/GoogleStorageFSSuite.scala @@ -15,17 +15,11 @@ class GoogleStorageFSSuite extends TestNGSuite with FSSuite { if (System.getenv("HAIL_CLOUD") != "gcp") { throw new SkipException("This test suite is only run in GCP."); } else { - assert(hail_test_storage_uri != null) + assert(root != null) assert(fsResourcesRoot != null) } } - val hail_test_storage_uri: String = System.getenv("HAIL_TEST_STORAGE_URI") - - val root: String = hail_test_storage_uri - - val fsResourcesRoot: String = System.getenv("HAIL_FS_TEST_CLOUD_RESOURCES_URI") - lazy val fs = { val gac = System.getenv("GOOGLE_APPLICATION_CREDENTIALS") if (gac == null) { @@ -36,8 +30,6 @@ class GoogleStorageFSSuite extends TestNGSuite with FSSuite { } } - lazy val tmpdir: String = hail_test_storage_uri - @Test def testMakeQualified(): Unit = { val qualifiedFileName = "gs://bucket/path" assert(fs.makeQualified(qualifiedFileName) == qualifiedFileName) @@ -52,34 +44,4 @@ class GoogleStorageFSSuite extends TestNGSuite with FSSuite { } assert(false) } - - @Test def deleteManyFiles(): Unit = { - val prefix = s"$hail_test_storage_uri/google-storage-fs-suite/delete-many-files/${ java.util.UUID.randomUUID() }" - for (i <- 0 until 2000) { - fs.touch(s"$prefix/$i") - } - assert(fs.exists(prefix)) - fs.delete(prefix, recursive = true) - assert(!fs.exists(prefix), s"files not deleted:\n${ fs.listStatus(prefix).map(_.getPath).mkString("\n") }") - } - - @Test def testSeekAfterEOF(): Unit = { - val prefix = s"$hail_test_storage_uri/google-storage-fs-suite/delete-many-files/${ java.util.UUID.randomUUID() }" - val p = s"$prefix/seek_file" - using(fs.createCachedNoCompression(p)) { os => - os.write(1.toByte) - os.write(2.toByte) - os.write(3.toByte) - os.write(4.toByte) - } - - using(fs.openNoCompression(p)) { is => - assert(is.read() == 1.toByte) - is.seek(3) - assert(is.read() == 4.toByte) - assert(is.read() == (-1).toByte) - is.seek(0) - assert(is.read() == 1.toByte) - } - } } From 5d545c8d9fb474ea211e350c5dc48c599db6f5ea Mon Sep 17 00:00:00 2001 From: jigold Date: Fri, 1 Sep 2023 22:14:30 -0400 Subject: [PATCH 173/180] [ci] Don't test PRs with do-not-test label (#13540) I added this feature because I am tired of every time I want to dev deploy and try out new changes, it triggers a new build in CI. I'd prefer to put a new label on the PR rather than close it each time or make a copy of the branch and test the copy. --- ci/ci/github.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ci/ci/github.py b/ci/ci/github.py index 32f03a9f0ea..a5df4fc368f 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -202,6 +202,7 @@ def __init__(self, exception: BaseException, attributes: Dict[str, str]): HIGH_PRIORITY = 'prio:high' STACKED_PR = 'stacked PR' WIP = 'WIP' +DO_NOT_TEST = 'do-not-test' DO_NOT_MERGE = {STACKED_PR, WIP} @@ -308,6 +309,9 @@ def build_succeeding_on_all_platforms(self): def build_failed_on_at_least_one_platform(self): return any(gh_status == GithubStatus.FAILURE for gh_status in self.last_known_github_status.values()) + def testable(self): + return DO_NOT_TEST not in self.labels + def merge_priority(self): # passed > unknown > failed if self.build_succeeding_on_all_platforms(): @@ -637,6 +641,9 @@ async def _heal(self, batch_client, db: Database, on_deck, gh): if not await self.authorized(db): return + if not self.testable(): + return + if not self.batch or (on_deck and self.batch.attributes['target_sha'] != self.target_branch.sha): if on_deck or self.target_branch.n_running_batches < MAX_CONCURRENT_PR_BATCHES: self.target_branch.n_running_batches += 1 From 076a587f598f108e2d0d2c750a6555ce404cfae5 Mon Sep 17 00:00:00 2001 From: Dan King Date: Sun, 3 Sep 2023 13:50:42 -0400 Subject: [PATCH 174/180] [query] avoid signed integer overlow in partition function (#13550) Not a correctness bug because we raise an assertion error in the partition function. --- hail/python/test/hail/table/test_table.py | 9 +++++++++ hail/src/main/scala/is/hail/utils/package.scala | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/hail/python/test/hail/table/test_table.py b/hail/python/test/hail/table/test_table.py index 92b8c28daf0..88d9518bb16 100644 --- a/hail/python/test/hail/table/test_table.py +++ b/hail/python/test/hail/table/test_table.py @@ -2504,3 +2504,12 @@ def test_query_table_interval_key(): def test_large_number_of_partitions(): ht = hl.utils.range_table(1500, n_partitions=1500) ht.collect() + + +def test_range_table_biggest_int(): + biggest_int32 = (1 << 31) - 1 + ht = hl.utils.range_table(biggest_int32) + + n = biggest_int32 - 1 # NB: range table is [0, ..., n - 1] + expected_sum = n * (n + 1) // 2 + assert expected_sum == ht.aggregate(hl.agg.sum(hl.int64(ht.idx))) diff --git a/hail/src/main/scala/is/hail/utils/package.scala b/hail/src/main/scala/is/hail/utils/package.scala index 10a45004988..ce99001cb63 100644 --- a/hail/src/main/scala/is/hail/utils/package.scala +++ b/hail/src/main/scala/is/hail/utils/package.scala @@ -690,7 +690,7 @@ package object utils extends Logging assert(n >= 0) assert(k > 0) - val parts = Array.tabulate(k)(i => (n - i + k - 1) / k) + val parts = Array.tabulate(k)(i => n / k + (i < (n % k)).toInt) assert(parts.sum == n) assert(parts.max - parts.min <= 1) parts @@ -704,7 +704,7 @@ package object utils extends Logging assert(n >= 0) assert(k > 0) - val parts = Array.tabulate(k)(i => (n - i + k - 1) / k) + val parts = Array.tabulate(k)(i => n / k + (i < (n % k)).toLong) assert(parts.sum == n) assert(parts.max - parts.min <= 1) parts From 5f8fcf5901564e85b36f0e6afe4494d902b08d36 Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 5 Sep 2023 11:33:06 -0400 Subject: [PATCH 175/180] [batch] Do not mount the xfs_quota from the worker host (#13544) --- batch/batch/cloud/gcp/driver/create_instance.py | 1 - 1 file changed, 1 deletion(-) diff --git a/batch/batch/cloud/gcp/driver/create_instance.py b/batch/batch/cloud/gcp/driver/create_instance.py index 374bf0d7272..963c4f0a748 100644 --- a/batch/batch/cloud/gcp/driver/create_instance.py +++ b/batch/batch/cloud/gcp/driver/create_instance.py @@ -362,7 +362,6 @@ def scheduling() -> dict: -v /var/run/docker.sock:/var/run/docker.sock \ -v /var/run/netns:/var/run/netns:shared \ -v /usr/bin/docker:/usr/bin/docker \ --v /usr/sbin/xfs_quota:/usr/sbin/xfs_quota \ -v /batch:/batch:shared \ -v /logs:/logs \ -v /global-config:/global-config \ From dbb28ae606035a091ef499f45fcafef29e68d61a Mon Sep 17 00:00:00 2001 From: Dan King Date: Tue, 5 Sep 2023 12:47:04 -0400 Subject: [PATCH 176/180] [batch] remove redundant super class (#13541) All these classes inherit from `Resource` which is an `abc.ABC`. --- batch/batch/cloud/azure/resources.py | 3 +-- batch/batch/cloud/gcp/resources.py | 3 +-- batch/batch/resources.py | 14 +++++++------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/batch/batch/cloud/azure/resources.py b/batch/batch/cloud/azure/resources.py index 0bf25885c53..e8f08a6c3c1 100644 --- a/batch/batch/cloud/azure/resources.py +++ b/batch/batch/cloud/azure/resources.py @@ -1,4 +1,3 @@ -import abc from typing import Any, Dict, Optional from ...driver.billing_manager import ProductVersions @@ -14,7 +13,7 @@ from .resource_utils import azure_disk_from_storage_in_gib, azure_disks_by_disk_type -class AzureResource(Resource, abc.ABC): +class AzureResource(Resource): pass diff --git a/batch/batch/cloud/gcp/resources.py b/batch/batch/cloud/gcp/resources.py index 22118531091..8218eb23cb7 100644 --- a/batch/batch/cloud/gcp/resources.py +++ b/batch/batch/cloud/gcp/resources.py @@ -1,4 +1,3 @@ -import abc from typing import Any, Dict, Optional from ...driver.billing_manager import ProductVersions @@ -14,7 +13,7 @@ ) -class GCPResource(Resource, abc.ABC): +class GCPResource(Resource): pass diff --git a/batch/batch/resources.py b/batch/batch/resources.py index d77589f0256..aa5dc778f11 100644 --- a/batch/batch/resources.py +++ b/batch/batch/resources.py @@ -33,7 +33,7 @@ def to_dict(self) -> dict: raise NotImplementedError -class StaticSizedDiskResourceMixin(Resource, abc.ABC): +class StaticSizedDiskResourceMixin(Resource): storage_in_gib: int def to_quantified_resource( @@ -44,7 +44,7 @@ def to_quantified_resource( return {'name': self.name, 'quantity': self.storage_in_gib * worker_fraction_in_1024ths} -class DynamicSizedDiskResourceMixin(Resource, abc.ABC): +class DynamicSizedDiskResourceMixin(Resource): @abc.abstractmethod def to_quantified_resource( self, cpu_in_mcpu: int, memory_in_bytes: int, worker_fraction_in_1024ths: int, external_storage_in_gib: int @@ -52,7 +52,7 @@ def to_quantified_resource( raise NotImplementedError -class ComputeResourceMixin(Resource, abc.ABC): +class ComputeResourceMixin(Resource): def to_quantified_resource( self, cpu_in_mcpu: int, memory_in_bytes: int, worker_fraction_in_1024ths: int, external_storage_in_gib: int ) -> Optional[QuantifiedResource]: # pylint: disable=unused-argument @@ -60,7 +60,7 @@ def to_quantified_resource( return {'name': self.name, 'quantity': cpu_in_mcpu} -class VMResourceMixin(Resource, abc.ABC): +class VMResourceMixin(Resource): def to_quantified_resource( self, cpu_in_mcpu: int, memory_in_bytes: int, worker_fraction_in_1024ths: int, external_storage_in_gib: int ) -> Optional[QuantifiedResource]: # pylint: disable=unused-argument @@ -68,7 +68,7 @@ def to_quantified_resource( return {'name': self.name, 'quantity': worker_fraction_in_1024ths} -class MemoryResourceMixin(Resource, abc.ABC): +class MemoryResourceMixin(Resource): def to_quantified_resource( self, cpu_in_mcpu: int, memory_in_bytes: int, worker_fraction_in_1024ths: int, external_storage_in_gib: int ) -> Optional[QuantifiedResource]: # pylint: disable=unused-argument @@ -76,7 +76,7 @@ def to_quantified_resource( return {'name': self.name, 'quantity': memory_in_bytes // 1024 // 1024} -class IPFeeResourceMixin(Resource, abc.ABC): +class IPFeeResourceMixin(Resource): def to_quantified_resource( self, cpu_in_mcpu: int, memory_in_bytes: int, worker_fraction_in_1024ths: int, external_storage_in_gib: int ) -> Optional[QuantifiedResource]: # pylint: disable=unused-argument @@ -84,7 +84,7 @@ def to_quantified_resource( return {'name': self.name, 'quantity': worker_fraction_in_1024ths} -class ServiceFeeResourceMixin(Resource, abc.ABC): +class ServiceFeeResourceMixin(Resource): def to_quantified_resource( self, cpu_in_mcpu: int, memory_in_bytes: int, worker_fraction_in_1024ths: int, external_storage_in_gib: int ) -> Optional[QuantifiedResource]: # pylint: disable=unused-argument From dc1f08622bcbbbbe55e232aa4f658dc07f7ee03b Mon Sep 17 00:00:00 2001 From: Daniel Goldstein Date: Tue, 5 Sep 2023 14:26:35 -0400 Subject: [PATCH 177/180] [auth] Allow use of cloud access tokens for hail batch authorization (#13131) Deprecate hail-minted API keys in favor of using access tokens from the identity providers already associated with user identities. For more context and a high-level overview of the implementation, see [this RFC](https://github.com/hail-is/hail-rfcs/pull/2) --- auth/auth/auth.py | 68 +++++- auth/auth/flow.py | 116 ---------- auth/pinned-requirements.txt | 75 ------- auth/requirements.txt | 1 - batch/Makefile | 2 +- .../cloud/azure/driver/create_instance.py | 4 + batch/batch/cloud/azure/worker/credentials.py | 6 + batch/batch/cloud/azure/worker/worker_api.py | 14 +- batch/batch/cloud/gcp/worker/credentials.py | 6 + batch/batch/cloud/gcp/worker/worker_api.py | 6 +- batch/batch/worker/credentials.py | 5 + batch/batch/worker/worker.py | 6 +- batch/batch/worker/worker_api.py | 7 +- batch/deployment.yaml | 7 + batch/test/test_batch.py | 14 +- batch/test/test_invariants.py | 3 +- build.yaml | 38 +++- ci/test/test_ci.py | 41 ++-- .../hailtop/aiocloud/aioazure/credentials.py | 82 ++++++- hail/python/hailtop/aiocloud/aioazure/fs.py | 4 +- .../hailtop/aiocloud/aiogoogle/credentials.py | 54 +++-- .../hailtop/aiocloud/common/credentials.py | 12 +- .../python/hailtop/aiocloud/common/session.py | 9 +- hail/python/hailtop/auth/__init__.py | 9 +- hail/python/hailtop/auth/auth.py | 184 +++++++++++----- hail/python/hailtop/auth/flow.py | 207 ++++++++++++++++++ hail/python/hailtop/auth/tokens.py | 3 + hail/python/hailtop/batch_client/aioclient.py | 5 +- hail/python/hailtop/config/__init__.py | 3 +- hail/python/hailtop/config/deploy_config.py | 14 +- hail/python/hailtop/config/user_config.py | 10 +- hail/python/hailtop/hailctl/auth/login.py | 107 ++------- hail/python/hailtop/pinned-requirements.txt | 7 +- hail/python/hailtop/requirements.txt | 1 + hail/python/pinned-requirements.txt | 6 + .../hail/backend/service/ServiceBackend.scala | 14 +- .../is/hail/backend/service/Worker.scala | 2 - .../scala/is/hail/services/DeployConfig.scala | 36 --- .../scala/is/hail/services/Requester.scala | 66 +++++- .../main/scala/is/hail/services/Tokens.scala | 69 ------ .../services/batch_client/BatchClient.scala | 17 +- .../batch_client/BatchClientSuite.scala | 2 +- infra/azure/modules/auth/main.tf | 43 ++++ monitoring/test/test_monitoring.py | 25 ++- notebook/scale-test.py | 3 +- 45 files changed, 825 insertions(+), 588 deletions(-) delete mode 100644 auth/auth/flow.py create mode 100644 hail/python/hailtop/auth/flow.py delete mode 100644 hail/src/main/scala/is/hail/services/Tokens.scala diff --git a/auth/auth/auth.py b/auth/auth/auth.py index 9c6283d0b33..985f0c0d201 100644 --- a/auth/auth/auth.py +++ b/auth/auth/auth.py @@ -33,6 +33,7 @@ from gear.cloud_config import get_global_config from gear.profiling import install_profiler_if_requested from hailtop import httpx +from hailtop.auth import AzureFlow, Flow, GoogleFlow, IdentityProvider from hailtop.config import get_deploy_config from hailtop.hail_logging import AccessLogger from hailtop.tls import internal_server_ssl_context @@ -51,7 +52,6 @@ PreviouslyDeletedUser, UnknownUser, ) -from .flow import get_flow_client log = logging.getLogger('auth') @@ -505,6 +505,12 @@ async def rest_login(request: web.Request) -> web.Response: ) +@routes.get('/api/v1alpha/oauth2-client') +async def hailctl_oauth_client(request): # pylint: disable=unused-argument + idp = IdentityProvider.GOOGLE if CLOUD == 'gcp' else IdentityProvider.MICROSOFT + return json_response({'idp': idp.value, 'oauth2_client': request.app['hailctl_client_config']}) + + @routes.get('/roles') @authenticated_devs_only async def get_roles(request: web.Request, userdata: UserData) -> web.Response: @@ -732,11 +738,51 @@ async def rest_logout(request: web.Request, userdata: UserData) -> web.Response: return web.Response(status=200) -async def get_userinfo(request: web.Request, session_id: str) -> UserData: +async def get_userinfo(request: web.Request, auth_token: str) -> UserData: + flow_client: Flow = request.app['flow_client'] + client_session = request.app['client_session'] + + userdata = await get_userinfo_from_hail_session_id(request, auth_token) + if userdata: + return userdata + + hailctl_oauth_client = request.app['hailctl_client_config'] + uid = await flow_client.get_identity_uid_from_access_token( + client_session, auth_token, oauth2_client=hailctl_oauth_client + ) + if uid: + return await get_userinfo_from_login_id_or_hail_identity_id(request, uid) + + raise web.HTTPUnauthorized() + + +async def get_userinfo_from_login_id_or_hail_identity_id( + request: web.Request, login_id_or_hail_idenity_uid: str +) -> UserData: + db = request.app['db'] + + users = [ + x + async for x in db.select_and_fetchall( + ''' +SELECT users.* +FROM users +WHERE (users.login_id = %s OR users.hail_identity_uid = %s) AND users.state = 'active' +''', + (login_id_or_hail_idenity_uid, login_id_or_hail_idenity_uid), + ) + ] + + if len(users) != 1: + log.info('Unknown login id') + raise web.HTTPUnauthorized() + return users[0] + + +async def get_userinfo_from_hail_session_id(request: web.Request, session_id: str) -> Optional[UserData]: # b64 encoding of 32-byte session ID is 44 bytes if len(session_id) != 44: - log.info('Session id != 44 bytes') - raise web.HTTPUnauthorized() + return None db = request.app['db'] users = [ @@ -753,8 +799,7 @@ async def get_userinfo(request: web.Request, session_id: str) -> UserData: ] if len(users) != 1: - log.info(f'Unknown session id: {session_id}') - raise web.HTTPUnauthorized() + return None return users[0] @@ -796,7 +841,16 @@ async def on_startup(app): await db.async_init(maxsize=50) app['db'] = db app['client_session'] = httpx.client_session() - app['flow_client'] = get_flow_client('/auth-oauth2-client-secret/client_secret.json') + + credentials_file = '/auth-oauth2-client-secret/client_secret.json' + if CLOUD == 'gcp': + app['flow_client'] = GoogleFlow(credentials_file) + else: + assert CLOUD == 'azure' + app['flow_client'] = AzureFlow(credentials_file) + + with open('/auth-oauth2-client-secret/hailctl_client_secret.json', 'r', encoding='utf-8') as f: + app['hailctl_client_config'] = json.loads(f.read()) kubernetes_asyncio.config.load_incluster_config() app['k8s_client'] = kubernetes_asyncio.client.CoreV1Api() diff --git a/auth/auth/flow.py b/auth/auth/flow.py deleted file mode 100644 index 9fb19a50345..00000000000 --- a/auth/auth/flow.py +++ /dev/null @@ -1,116 +0,0 @@ -import abc -import json -import urllib.parse -from typing import Any, ClassVar, List, Mapping - -import aiohttp.web -import google.auth.transport.requests -import google.oauth2.id_token -import google_auth_oauthlib.flow -import msal - -from gear.cloud_config import get_global_config - - -class FlowResult: - def __init__(self, login_id: str, email: str, token: Mapping[Any, Any]): - self.login_id = login_id - self.email = email - self.token = token - - -class Flow(abc.ABC): - @abc.abstractmethod - def initiate_flow(self, redirect_uri: str) -> dict: - """ - Initiates the OAuth2 flow. Usually run in response to a user clicking a login button. - The returned dict should be stored in a secure session so that the server can - identify to which OAuth2 flow a client is responding. In particular, the server must - pass this dict to :meth:`.receive_callback` in the OAuth2 callback. - """ - raise NotImplementedError - - @abc.abstractmethod - def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> FlowResult: - """Concludes the OAuth2 flow by returning the user's identity and credentials.""" - raise NotImplementedError - - -class GoogleFlow(Flow): - scopes: ClassVar[List[str]] = [ - 'https://www.googleapis.com/auth/userinfo.profile', - 'https://www.googleapis.com/auth/userinfo.email', - 'openid', - ] - - def __init__(self, credentials_file: str): - self._credentials_file = credentials_file - - def initiate_flow(self, redirect_uri: str) -> dict: - flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( - self._credentials_file, scopes=self.scopes, state=None - ) - flow.redirect_uri = redirect_uri - authorization_url, state = flow.authorization_url(access_type='offline', include_granted_scopes='true') - - return { - 'authorization_url': authorization_url, - 'redirect_uri': redirect_uri, - 'state': state, - } - - def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> FlowResult: - flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( - self._credentials_file, scopes=self.scopes, state=flow_dict['state'] - ) - flow.redirect_uri = flow_dict['callback_uri'] - flow.fetch_token(code=request.query['code']) - token = google.oauth2.id_token.verify_oauth2_token( - flow.credentials.id_token, google.auth.transport.requests.Request() # type: ignore - ) - email = token['email'] - return FlowResult(email, email, token) - - -class AzureFlow(Flow): - def __init__(self, credentials_file: str): - with open(credentials_file, encoding='utf-8') as f: - data = json.loads(f.read()) - - tenant_id = data['tenant'] - authority = f'https://login.microsoftonline.com/{tenant_id}' - client = msal.ConfidentialClientApplication(data['appId'], data['password'], authority) - - self._client = client - self._tenant_id = tenant_id - - def initiate_flow(self, redirect_uri: str) -> dict: - flow = self._client.initiate_auth_code_flow(scopes=[], redirect_uri=redirect_uri) - return { - 'flow': flow, - 'authorization_url': flow['auth_uri'], - 'state': flow['state'], - } - - def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> FlowResult: - query_key_to_list_of_values = urllib.parse.parse_qs(request.query_string) - query_dict = {k: v[0] for k, v in query_key_to_list_of_values.items()} - - token = self._client.acquire_token_by_auth_code_flow(flow_dict['flow'], query_dict) - - if 'error' in token: - raise ValueError(token) - - tid = token['id_token_claims']['tid'] - if tid != self._tenant_id: - raise ValueError('invalid tenant id') - - return FlowResult(token['id_token_claims']['oid'], token['id_token_claims']['preferred_username'], token) - - -def get_flow_client(credentials_file: str) -> Flow: - cloud = get_global_config()['cloud'] - if cloud == 'azure': - return AzureFlow(credentials_file) - assert cloud == 'gcp' - return GoogleFlow(credentials_file) diff --git a/auth/pinned-requirements.txt b/auth/pinned-requirements.txt index a94488a6fe8..59a01b5036e 100644 --- a/auth/pinned-requirements.txt +++ b/auth/pinned-requirements.txt @@ -4,78 +4,3 @@ # # pip-compile --output-file=hail/auth/pinned-requirements.txt hail/auth/requirements.txt # -cachetools==5.3.1 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # google-auth -certifi==2023.7.22 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/dev/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # requests -charset-normalizer==3.2.0 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/dev/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # -c hail/auth/../web_common/pinned-requirements.txt - # requests -google-auth==2.22.0 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # google-auth-oauthlib -google-auth-oauthlib==0.8.0 - # via -r hail/auth/requirements.txt -idna==3.4 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/dev/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # -c hail/auth/../web_common/pinned-requirements.txt - # requests -oauthlib==3.2.2 - # via - # -c hail/auth/../hail/python/pinned-requirements.txt - # requests-oauthlib -pyasn1==0.5.0 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # pyasn1-modules - # rsa -pyasn1-modules==0.3.0 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # google-auth -requests==2.31.0 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/dev/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # requests-oauthlib -requests-oauthlib==1.3.1 - # via - # -c hail/auth/../hail/python/pinned-requirements.txt - # google-auth-oauthlib -rsa==4.9 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # google-auth -six==1.16.0 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/dev/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # google-auth -urllib3==1.26.16 - # via - # -c hail/auth/../gear/pinned-requirements.txt - # -c hail/auth/../hail/python/dev/pinned-requirements.txt - # -c hail/auth/../hail/python/pinned-requirements.txt - # google-auth - # requests diff --git a/auth/requirements.txt b/auth/requirements.txt index f9a32c9b631..64f46f9bbb8 100644 --- a/auth/requirements.txt +++ b/auth/requirements.txt @@ -2,4 +2,3 @@ -c ../hail/python/dev/pinned-requirements.txt -c ../gear/pinned-requirements.txt -c ../web_common/pinned-requirements.txt -google-auth-oauthlib>=0.5.2,<1 diff --git a/batch/Makefile b/batch/Makefile index e608fcd17e9..ba9ce759da6 100644 --- a/batch/Makefile +++ b/batch/Makefile @@ -4,7 +4,7 @@ include ../config.mk build: $(MAKE) -C .. batch-image batch-worker-image -JINJA_ENVIRONMENT = '{"code":{"sha":"$(shell git rev-parse --short=12 HEAD)"},"deploy":$(DEPLOY),"batch_image":{"image":"$(shell cat ../batch-image)"},"batch_worker_image":{"image":"$(shell cat ../batch-worker-image)"},"default_ns":{"name":"$(NAMESPACE)"},"batch_database":{"user_secret_name":"sql-batch-user-config"},"scope":"$(SCOPE)","global":{"docker_prefix":"$(DOCKER_PREFIX)"}}' +JINJA_ENVIRONMENT = '{"code":{"sha":"$(shell git rev-parse --short=12 HEAD)"},"deploy":$(DEPLOY),"batch_image":{"image":"$(shell cat ../batch-image)"},"batch_worker_image":{"image":"$(shell cat ../batch-worker-image)"},"default_ns":{"name":"$(NAMESPACE)"},"batch_database":{"user_secret_name":"sql-batch-user-config"},"scope":"$(SCOPE)","global":{"docker_prefix":"$(DOCKER_PREFIX)","cloud":"$(CLOUD)"}}' .PHONY: deploy deploy: build diff --git a/batch/batch/cloud/azure/driver/create_instance.py b/batch/batch/cloud/azure/driver/create_instance.py index ceffb1c1720..6602c8d8074 100644 --- a/batch/batch/cloud/azure/driver/create_instance.py +++ b/batch/batch/cloud/azure/driver/create_instance.py @@ -45,6 +45,7 @@ def create_vm_config( ) -> dict: _, cores = azure_machine_type_to_worker_type_and_cores(machine_type) + hail_azure_oauth_scope = os.environ['HAIL_AZURE_OAUTH_SCOPE'] region = instance_config.region_for(location) if max_price is not None and not preemptible: @@ -205,6 +206,7 @@ def create_vm_config( DOCKER_ROOT_IMAGE=$(jq -r '.docker_root_image' userdata) DOCKER_PREFIX=$(jq -r '.docker_prefix' userdata) REGION=$(jq -r '.region' userdata) +HAIL_AZURE_OAUTH_SCOPE=$(jq -r '.hail_azure_oauth_scope' userdata) INTERNAL_GATEWAY_IP=$(jq -r '.internal_ip' userdata) @@ -259,6 +261,7 @@ def create_vm_config( -e RESOURCE_GROUP=$RESOURCE_GROUP \ -e LOCATION=$LOCATION \ -e REGION=$REGION \ +-e HAIL_AZURE_OAUTH_SCOPE=$HAIL_AZURE_OAUTH_SCOPE \ -e DOCKER_PREFIX=$DOCKER_PREFIX \ -e DOCKER_ROOT_IMAGE=$DOCKER_ROOT_IMAGE \ -e INSTANCE_CONFIG=$INSTANCE_CONFIG \ @@ -314,6 +317,7 @@ def create_vm_config( 'max_idle_time_msecs': max_idle_time_msecs, 'instance_config': base64.b64encode(json.dumps(instance_config.to_dict()).encode()).decode(), 'region': region, + 'hail_azure_oauth_scope': hail_azure_oauth_scope, } user_data_str = base64.b64encode(json.dumps(user_data).encode('utf-8')).decode('utf-8') diff --git a/batch/batch/cloud/azure/worker/credentials.py b/batch/batch/cloud/azure/worker/credentials.py index 7b7662e4a05..0488b1537f1 100644 --- a/batch/batch/cloud/azure/worker/credentials.py +++ b/batch/batch/cloud/azure/worker/credentials.py @@ -2,6 +2,8 @@ import json from typing import Dict +from hailtop.auth.auth import IdentityProvider + from ....worker.credentials import CloudUserCredentials @@ -26,6 +28,10 @@ def password(self): def mount_path(self): return '/azure-credentials/key.json' + @property + def identity_provider_json(self): + return {'idp': IdentityProvider.MICROSOFT.value} + def blobfuse_credentials(self, account: str, container: str) -> str: # https://github.com/Azure/azure-storage-fuse return f''' diff --git a/batch/batch/cloud/azure/worker/worker_api.py b/batch/batch/cloud/azure/worker/worker_api.py index 6e65d97dc3f..a8cf68cdbb9 100644 --- a/batch/batch/cloud/azure/worker/worker_api.py +++ b/batch/batch/cloud/azure/worker/worker_api.py @@ -1,7 +1,7 @@ import abc import os import tempfile -from typing import Dict, Optional, Tuple +from typing import Dict, List, Optional, Tuple import aiohttp @@ -23,16 +23,22 @@ def from_env(): subscription_id = os.environ['SUBSCRIPTION_ID'] resource_group = os.environ['RESOURCE_GROUP'] acr_url = os.environ['DOCKER_PREFIX'] + hail_oauth_scope = os.environ['HAIL_AZURE_OAUTH_SCOPE'] assert acr_url.endswith('azurecr.io'), acr_url - return AzureWorkerAPI(subscription_id, resource_group, acr_url) + return AzureWorkerAPI(subscription_id, resource_group, acr_url, hail_oauth_scope) - def __init__(self, subscription_id: str, resource_group: str, acr_url: str): + def __init__(self, subscription_id: str, resource_group: str, acr_url: str, hail_oauth_scope: str): self.subscription_id = subscription_id self.resource_group = resource_group + self.hail_oauth_scope = hail_oauth_scope self.azure_credentials = aioazure.AzureCredentials.default_credentials() self.acr_refresh_token = AcrRefreshToken(acr_url, self.azure_credentials) self._blobfuse_credential_files: Dict[str, str] = {} + @property + def cloud_specific_env_vars_for_user_jobs(self) -> List[str]: + return [f'HAIL_AZURE_OAUTH_SCOPE={self.hail_oauth_scope}'] + def create_disk(self, instance_name: str, disk_name: str, size_in_gb: int, mount_path: str) -> AzureDisk: return AzureDisk(disk_name, instance_name, size_in_gb, mount_path) @@ -151,7 +157,7 @@ async def _fetch(self, session: httpx.ClientSession) -> Tuple[str, int]: data = { 'grant_type': 'access_token', 'service': self.acr_url, - 'access_token': (await self.credentials.access_token()).token, + 'access_token': await self.credentials.access_token(), } resp_json = await retry_transient_errors( session.post_read_json, diff --git a/batch/batch/cloud/gcp/worker/credentials.py b/batch/batch/cloud/gcp/worker/credentials.py index 86d7b824b0b..b637ef4e951 100644 --- a/batch/batch/cloud/gcp/worker/credentials.py +++ b/batch/batch/cloud/gcp/worker/credentials.py @@ -1,6 +1,8 @@ import base64 from typing import Dict +from hailtop.auth.auth import IdentityProvider + from ....worker.credentials import CloudUserCredentials @@ -20,3 +22,7 @@ def mount_path(self): @property def key(self): return self._key + + @property + def identity_provider_json(self): + return {'idp': IdentityProvider.GOOGLE.value} diff --git a/batch/batch/cloud/gcp/worker/worker_api.py b/batch/batch/cloud/gcp/worker/worker_api.py index d876abc7532..19c431f6c06 100644 --- a/batch/batch/cloud/gcp/worker/worker_api.py +++ b/batch/batch/cloud/gcp/worker/worker_api.py @@ -1,6 +1,6 @@ import os import tempfile -from typing import Dict +from typing import Dict, List import aiohttp @@ -32,6 +32,10 @@ def __init__(self, project: str, zone: str, session: aiogoogle.GoogleSession): self._compute_client = aiogoogle.GoogleComputeClient(project, session=session) self._gcsfuse_credential_files: Dict[str, str] = {} + @property + def cloud_specific_env_vars_for_user_jobs(self) -> List[str]: + return [] + def create_disk(self, instance_name: str, disk_name: str, size_in_gb: int, mount_path: str) -> GCPDisk: return GCPDisk( zone=self.zone, diff --git a/batch/batch/worker/credentials.py b/batch/batch/worker/credentials.py index 064924e1a6e..e2f22b0905c 100644 --- a/batch/batch/worker/credentials.py +++ b/batch/batch/worker/credentials.py @@ -11,3 +11,8 @@ def cloud_env_name(self) -> str: @abc.abstractmethod def mount_path(self): raise NotImplementedError + + @property + @abc.abstractmethod + def identity_provider_json(self) -> dict: + raise NotImplementedError diff --git a/batch/batch/worker/worker.py b/batch/batch/worker/worker.py index 32a118f94de..0026aae326f 100644 --- a/batch/batch/worker/worker.py +++ b/batch/batch/worker/worker.py @@ -1330,7 +1330,10 @@ def _mounts(self, uid: int, gid: int) -> List[MountSpecification]: def _env(self): assert self.image.image_config - env = self.image.image_config['Config']['Env'] + self.env + assert CLOUD_WORKER_API + env = ( + self.image.image_config['Config']['Env'] + self.env + CLOUD_WORKER_API.cloud_specific_env_vars_for_user_jobs + ) if self.port is not None: assert self.host_port is not None env.append(f'HAIL_BATCH_WORKER_PORT={self.host_port}') @@ -1707,6 +1710,7 @@ def __init__( hail_extra_env = [ {'name': 'HAIL_REGION', 'value': REGION}, {'name': 'HAIL_BATCH_ID', 'value': str(batch_id)}, + {'name': 'HAIL_IDENTITY_PROVIDER_JSON', 'value': json.dumps(self.credentials.identity_provider_json)}, ] self.env += hail_extra_env diff --git a/batch/batch/worker/worker_api.py b/batch/batch/worker/worker_api.py index 8bc2f9d3ea9..8e6f8698835 100644 --- a/batch/batch/worker/worker_api.py +++ b/batch/batch/worker/worker_api.py @@ -1,5 +1,5 @@ import abc -from typing import Dict, Generic, TypedDict, TypeVar +from typing import Dict, Generic, List, TypedDict, TypeVar from hailtop import httpx from hailtop.aiotools.fs import AsyncFS @@ -20,6 +20,11 @@ class ContainerRegistryCredentials(TypedDict): class CloudWorkerAPI(abc.ABC, Generic[CredsType]): nameserver_ip: str + @property + @abc.abstractmethod + def cloud_specific_env_vars_for_user_jobs(self) -> List[str]: + raise NotImplementedError + @abc.abstractmethod def create_disk(self, instance_name: str, disk_name: str, size_in_gb: int, mount_path: str) -> CloudDisk: raise NotImplementedError diff --git a/batch/deployment.yaml b/batch/deployment.yaml index b9322cab16d..482f4d4508a 100644 --- a/batch/deployment.yaml +++ b/batch/deployment.yaml @@ -213,6 +213,13 @@ spec: secretKeyRef: name: global-config key: internal_ip +{% if global.cloud == "azure" %} + - name: HAIL_AZURE_OAUTH_SCOPE + valueFrom: + secretKeyRef: + name: auth-oauth2-client-secret + key: sp_oauth_scope +{% endif %} - name: HAIL_SHA value: "{{ code.sha }}" {% if scope != "test" %} diff --git a/batch/test/test_batch.py b/batch/test/test_batch.py index 548a5532748..c8ab00006bd 100644 --- a/batch/test/test_batch.py +++ b/batch/test/test_batch.py @@ -1074,7 +1074,8 @@ async def test_batch_create_validation(): {'attributes': {'k': None}, 'billing_project': 'foo', 'n_jobs': 5, 'token': 'baz'}, ] url = deploy_config.url('batch', '/api/v1alpha/batches/create') - headers = await hail_credentials().auth_headers() + async with hail_credentials() as creds: + headers = await creds.auth_headers() session = external_requests_client_session() for config in bad_configs: r = retry_response_returning_functions(session.post, url, json=config, allow_redirects=True, headers=headers) @@ -1154,10 +1155,9 @@ def test_cant_submit_to_default_with_other_ns_creds(client: BatchClient, remote_ '/bin/bash', '-c', f''' -hailctl config set domain {DOMAIN} -export HAIL_DEFAULT_NAMESPACE=default python3 -c \'{script}\'''', ], + env={'HAIL_DOMAIN': DOMAIN, 'HAIL_DEFAULT_NAMESPACE': 'default', 'HAIL_LOCATION': 'external'}, mount_tokens=True, ) b.submit() @@ -1166,7 +1166,7 @@ def test_cant_submit_to_default_with_other_ns_creds(client: BatchClient, remote_ assert status['state'] == 'Success', str((status, b.debug_info())) else: assert status['state'] == 'Failed', str((status, b.debug_info())) - assert "Please log in" in j.log()['main'], (str(j.log()['main']), status) + assert 'Unauthorized' in j.log()['main'], (str(j.log()['main']), status) def test_deploy_config_is_mounted_as_readonly(client: BatchClient): @@ -1251,11 +1251,11 @@ def test_hadoop_can_use_cloud_credentials(client: BatchClient, remote_tmpdir: st def test_user_authentication_within_job(client: BatchClient): b = create_batch(client) cmd = ['bash', '-c', 'hailctl auth user'] - no_token = b.create_job(HAIL_GENETICS_HAILTOP_IMAGE, cmd, mount_tokens=False) + no_token = b.create_job(HAIL_GENETICS_HAILTOP_IMAGE, cmd) b.submit() - no_token_status = no_token.wait() - assert no_token_status['state'] == 'Failed', str((no_token_status, b.debug_info())) + status = no_token.wait() + assert status['state'] == 'Success', str((status, b.debug_info())) def test_verify_access_to_public_internet(client: BatchClient): diff --git a/batch/test/test_invariants.py b/batch/test/test_invariants.py index 545319b8983..8870397dc2c 100644 --- a/batch/test/test_invariants.py +++ b/batch/test/test_invariants.py @@ -17,7 +17,8 @@ async def test_invariants(): deploy_config = get_deploy_config() url = deploy_config.url('batch-driver', '/check_invariants') - headers = await hail_credentials().auth_headers() + async with hail_credentials() as credentials: + headers = await credentials.auth_headers() async with client_session(timeout=aiohttp.ClientTimeout(total=60)) as session: data = await retry_transient_errors(session.get_read_json, url, headers=headers) diff --git a/build.yaml b/build.yaml index b9a9a35aa48..43a42538360 100644 --- a/build.yaml +++ b/build.yaml @@ -2378,6 +2378,7 @@ steps: {% elif global.cloud == "azure" %} export HAIL_AZURE_SUBSCRIPTION_ID={{ global.azure_subscription_id }} export HAIL_AZURE_RESOURCE_GROUP={{ global.azure_resource_group }} + export HAIL_AZURE_OAUTH_SCOPE=$(cat /oauth-secret/sp_oauth_scope) {% endif %} export HAIL_SHUFFLE_MAX_BRANCH=4 @@ -2504,6 +2505,10 @@ steps: namespace: valueFrom: default_ns.name mountPath: /user-tokens + - name: auth-oauth2-client-secret + namespace: + valueFrom: default_ns.name + mountPath: /oauth-secret dependsOn: - default_ns - merge_code @@ -2924,7 +2929,19 @@ steps: export HAIL_DEFAULT_NAMESPACE={{ default_ns.name }} export HAIL_GENETICS_HAIL_IMAGE="{{ hailgenetics_hail_image.image }}" + + {% if global.cloud == "gcp" %} + export HAIL_IDENTITY_PROVIDER_JSON='{"idp": "Google"}' export GOOGLE_APPLICATION_CREDENTIALS=/test-gsa-key/key.json + {% elif global.cloud == "azure" %} + export HAIL_IDENTITY_PROVIDER_JSON='{"idp": "Microsoft"}' + export HAIL_AZURE_OAUTH_SCOPE=$(cat /oauth-secret/sp_oauth_scope) + export AZURE_APPLICATION_CREDENTIALS=/test-gsa-key/key.json + {% else %} + echo "unknown cloud {{ global.cloud }}" + exit 1 + {% endif %} + hailctl config set batch/billing_project test hailctl config set batch/remote_tmpdir {{ global.test_storage_uri }}/hailctl-test/{{ token }} @@ -3009,14 +3026,14 @@ steps: exit 1; fi secrets: - - name: test-tokens - namespace: - valueFrom: default_ns.name - mountPath: /user-tokens - name: test-gsa-key namespace: valueFrom: default_ns.name mountPath: /test-gsa-key + - name: auth-oauth2-client-secret + namespace: + valueFrom: default_ns.name + mountPath: /oauth-secret dependsOn: - hailgenetics_hail_image - upload_query_jar @@ -3524,7 +3541,12 @@ steps: cpu: '2' script: | set -ex + + export HAIL_CLOUD={{ global.cloud }} export HAIL_DEFAULT_NAMESPACE={{ default_ns.name }} + {% if global.cloud == "azure" %} + export HAIL_AZURE_OAUTH_SCOPE=$(cat /oauth-secret/sp_oauth_scope) + {% endif %} cd /io mkdir -p src/test @@ -3542,10 +3564,14 @@ steps: - from: /repo/hail/testng-services.xml to: /io/testng-services.xml secrets: - - name: test-tokens + - name: test-gsa-key namespace: valueFrom: default_ns.name - mountPath: /user-tokens + mountPath: /test-gsa-key + - name: auth-oauth2-client-secret + namespace: + valueFrom: default_ns.name + mountPath: /oauth-secret timeout: 1200 dependsOn: - default_ns diff --git a/ci/test/test_ci.py b/ci/test/test_ci.py index 1d6045d33cf..285866a037c 100644 --- a/ci/test/test_ci.py +++ b/ci/test/test_ci.py @@ -17,25 +17,26 @@ async def test_deploy(): deploy_config = get_deploy_config() ci_deploy_status_url = deploy_config.url('ci', '/api/v1alpha/deploy_status') - headers = await hail_credentials().auth_headers() - async with client_session() as session: + async with hail_credentials() as creds: + async with client_session() as session: - async def wait_forever(): - deploy_state = None - deploy_status = None - failure_information = None - while deploy_state is None: - deploy_statuses = await retry_transient_errors( - session.get_read_json, ci_deploy_status_url, headers=headers - ) - log.info(f'deploy_statuses:\n{json.dumps(deploy_statuses, indent=2)}') - assert len(deploy_statuses) == 1, deploy_statuses - deploy_status = deploy_statuses[0] - deploy_state = deploy_status['deploy_state'] - failure_information = deploy_status.get('failure_information') - await asyncio.sleep(5) - log.info(f'returning {deploy_status} {failure_information}') - return deploy_state, failure_information + async def wait_forever(): + deploy_state = None + deploy_status = None + failure_information = None + while deploy_state is None: + headers = await creds.auth_headers() + deploy_statuses = await retry_transient_errors( + session.get_read_json, ci_deploy_status_url, headers=headers + ) + log.info(f'deploy_statuses:\n{json.dumps(deploy_statuses, indent=2)}') + assert len(deploy_statuses) == 1, deploy_statuses + deploy_status = deploy_statuses[0] + deploy_state = deploy_status['deploy_state'] + failure_information = deploy_status.get('failure_information') + await asyncio.sleep(5) + log.info(f'returning {deploy_status} {failure_information}') + return deploy_state, failure_information - deploy_state, failure_information = await wait_forever() - assert deploy_state == 'success', str(failure_information) + deploy_state, failure_information = await wait_forever() + assert deploy_state == 'success', str(failure_information) diff --git a/hail/python/hailtop/aiocloud/aioazure/credentials.py b/hail/python/hailtop/aiocloud/aioazure/credentials.py index 25abbeafb66..a13694db2b9 100644 --- a/hail/python/hailtop/aiocloud/aioazure/credentials.py +++ b/hail/python/hailtop/aiocloud/aioazure/credentials.py @@ -1,24 +1,85 @@ +import concurrent.futures import os import json import time import logging -from typing import List, Optional + +from types import TracebackType +from typing import Any, List, Optional, Type, Union from azure.identity.aio import DefaultAzureCredential, ClientSecretCredential +from azure.core.credentials import AccessToken +from azure.core.credentials_async import AsyncTokenCredential + +import msal -from hailtop.utils import first_extant_file +from hailtop.utils import first_extant_file, blocking_to_async from ..common.credentials import CloudCredentials log = logging.getLogger(__name__) +class RefreshTokenCredential(AsyncTokenCredential): + def __init__(self, client_id: str, tenant_id: str, refresh_token: str): + authority = f'https://login.microsoftonline.com/{tenant_id}' + self._app = msal.PublicClientApplication(client_id, authority=authority) + self._pool = concurrent.futures.ThreadPoolExecutor() + self._refresh_token: Optional[str] = refresh_token + + async def get_token( + self, *scopes: str, claims: Optional[str] = None, tenant_id: Optional[str] = None, **kwargs: Any + ) -> AccessToken: + # MSAL token objects, like those returned from `acquire_token_by_refresh_token` do their own internal + # caching of refresh tokens. Per their documentation it is not advised to use the original refresh token + # once you have "migrated it into MSAL". + # See docs: + # https://msal-python.readthedocs.io/en/latest/#msal.ClientApplication.acquire_token_by_refresh_token + if self._refresh_token: + res_co = blocking_to_async(self._pool, self._app.acquire_token_by_refresh_token, self._refresh_token, scopes) + self._refresh_token = None + res = await res_co + else: + res = await blocking_to_async(self._pool, self._app.acquire_token_silent, scopes, None) + assert res + return AccessToken(res['access_token'], res['id_token_claims']['exp']) # type: ignore + + async def __aenter__(self): + return self + + async def __aexit__( + self, + exc_type: Optional[Type[BaseException]] = None, + exc_value: Optional[BaseException] = None, + traceback: Optional[TracebackType] = None, + ) -> None: + await self.close() + + async def close(self) -> None: + self._pool.shutdown() + + class AzureCredentials(CloudCredentials): @staticmethod def from_credentials_data(credentials: dict, scopes: Optional[List[str]] = None): - credential = ClientSecretCredential(tenant_id=credentials['tenant'], - client_id=credentials['appId'], - client_secret=credentials['password']) - return AzureCredentials(credential, scopes) + if 'refreshToken' in credentials: + return AzureCredentials( + RefreshTokenCredential( + client_id=credentials['appId'], + tenant_id=credentials['tenant'], + refresh_token=credentials['refreshToken'], + ), + scopes=scopes, + ) + + assert 'password' in credentials + return AzureCredentials( + ClientSecretCredential( + tenant_id=credentials['tenant'], + client_id=credentials['appId'], + client_secret=credentials['password'] + ), + scopes + ) @staticmethod def from_file(credentials_file: str, scopes: Optional[List[str]] = None): @@ -40,7 +101,7 @@ def default_credentials(scopes: Optional[List[str]] = None): return AzureCredentials(DefaultAzureCredential(), scopes) - def __init__(self, credential, scopes: Optional[List[str]] = None): + def __init__(self, credential: Union[DefaultAzureCredential, ClientSecretCredential, RefreshTokenCredential], scopes: Optional[List[str]] = None): self.credential = credential self._access_token = None self._expires_at = None @@ -51,14 +112,15 @@ def __init__(self, credential, scopes: Optional[List[str]] = None): async def auth_headers(self): access_token = await self.access_token() - return {'Authorization': f'Bearer {access_token.token}'} # type: ignore + return {'Authorization': f'Bearer {access_token}'} - async def access_token(self): + async def access_token(self) -> str: now = time.time() if self._access_token is None or (self._expires_at is not None and now > self._expires_at): self._access_token = await self.get_access_token() self._expires_at = now + (self._access_token.expires_on - now) // 2 # type: ignore - return self._access_token + assert self._access_token + return self._access_token.token async def get_access_token(self): return await self.credential.get_token(*self.scopes) diff --git a/hail/python/hailtop/aiocloud/aioazure/fs.py b/hail/python/hailtop/aiocloud/aioazure/fs.py index 5e61adeef20..e2d60adbe09 100644 --- a/hail/python/hailtop/aiocloud/aioazure/fs.py +++ b/hail/python/hailtop/aiocloud/aioazure/fs.py @@ -388,7 +388,7 @@ async def generate_sas_token( valid_interval: timedelta = timedelta(hours=1) ) -> str: assert self._credential - mgmt_client = StorageManagementClient(self._credential, subscription_id) + mgmt_client = StorageManagementClient(self._credential, subscription_id) # type: ignore storage_keys = await mgmt_client.storage_accounts.list_keys(resource_group, account) storage_key = storage_keys.keys[0].value # type: ignore @@ -458,7 +458,7 @@ def get_blob_service_client(self, account: str, container: str, token: Optional[ if k not in self._blob_service_clients: # https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/storage/azure-storage-blob#other-client--per-operation-configuration self._blob_service_clients[k] = BlobServiceClient(f'https://{account}.blob.core.windows.net', - credential=credential, + credential=credential, # type: ignore connection_timeout=5, read_timeout=5) return self._blob_service_clients[k] diff --git a/hail/python/hailtop/aiocloud/aiogoogle/credentials.py b/hail/python/hailtop/aiocloud/aiogoogle/credentials.py index 1f182c64b7d..49bb6f0c71f 100644 --- a/hail/python/hailtop/aiocloud/aiogoogle/credentials.py +++ b/hail/python/hailtop/aiocloud/aiogoogle/credentials.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional, Union +from typing import Dict, Optional, Union, List, Literal, ClassVar, overload import os import json import time @@ -6,8 +6,9 @@ import socket from urllib.parse import urlencode import jwt + from hailtop.utils import retry_transient_errors -import hailtop.httpx +from hailtop import httpx from ..common.credentials import AnonymousCloudCredentials, CloudCredentials log = logging.getLogger(__name__) @@ -31,37 +32,53 @@ def expired(self) -> bool: class GoogleCredentials(CloudCredentials): - _http_session: hailtop.httpx.ClientSession + default_scopes: ClassVar[List[str]] = [ + 'openid', + 'https://www.googleapis.com/auth/userinfo.email', + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/appengine.admin', + 'https://www.googleapis.com/auth/compute', + ] def __init__(self, - http_session: Optional[hailtop.httpx.ClientSession] = None, + http_session: Optional[httpx.ClientSession] = None, + scopes: Optional[List[str]] = None, **kwargs): self._access_token: Optional[GoogleExpiringAccessToken] = None + self._scopes = scopes or GoogleCredentials.default_scopes if http_session is not None: assert len(kwargs) == 0 self._http_session = http_session else: - self._http_session = hailtop.httpx.ClientSession(**kwargs) + self._http_session = httpx.ClientSession(**kwargs) @staticmethod - def from_file(credentials_file: str) -> 'GoogleCredentials': + def from_file(credentials_file: str, *, scopes: Optional[List[str]] = None) -> 'GoogleCredentials': with open(credentials_file, encoding='utf-8') as f: credentials = json.load(f) - return GoogleCredentials.from_credentials_data(credentials) + return GoogleCredentials.from_credentials_data(credentials, scopes=scopes) @staticmethod - def from_credentials_data(credentials: dict, **kwargs) -> 'GoogleCredentials': + def from_credentials_data(credentials: dict, scopes: Optional[List[str]] = None, **kwargs) -> 'GoogleCredentials': credentials_type = credentials['type'] if credentials_type == 'service_account': - return GoogleServiceAccountCredentials(credentials, **kwargs) + return GoogleServiceAccountCredentials(credentials, scopes=scopes, **kwargs) if credentials_type == 'authorized_user': - return GoogleApplicationDefaultCredentials(credentials, **kwargs) + return GoogleApplicationDefaultCredentials(credentials, scopes=scopes, **kwargs) raise ValueError(f'unknown Google Cloud credentials type {credentials_type}') + @overload + @staticmethod + def default_credentials(scopes: Optional[List[str]] = ..., *, anonymous_ok: Literal[False] = ...) -> 'GoogleCredentials': ... + + @overload @staticmethod - def default_credentials() -> Union['GoogleCredentials', AnonymousCloudCredentials]: + def default_credentials(scopes: Optional[List[str]] = ..., *, anonymous_ok: Literal[True] = ...) -> Union['GoogleCredentials', AnonymousCloudCredentials]: ... + + @staticmethod + def default_credentials(scopes: Optional[List[str]] = None, *, anonymous_ok: bool = True) -> Union['GoogleCredentials', AnonymousCloudCredentials]: credentials_file = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS') if credentials_file is None: @@ -71,23 +88,30 @@ def default_credentials() -> Union['GoogleCredentials', AnonymousCloudCredential credentials_file = application_default_credentials_file if credentials_file: - creds = GoogleCredentials.from_file(credentials_file) + creds = GoogleCredentials.from_file(credentials_file, scopes=scopes) log.info(f'using credentials file {credentials_file}: {creds}') return creds log.info('Unable to locate Google Cloud credentials file') if GoogleInstanceMetadataCredentials.available(): log.info('Will attempt to use instance metadata server instead') - return GoogleInstanceMetadataCredentials() + return GoogleInstanceMetadataCredentials(scopes=scopes) + if not anonymous_ok: + raise ValueError( + 'No valid Google Cloud credentials found. Run `gcloud auth application-default login` or set `GOOGLE_APPLICATION_CREDENTIALS`.' + ) log.warning('Using anonymous credentials. If accessing private data, ' 'run `gcloud auth application-default login` first to log in.') return AnonymousCloudCredentials() async def auth_headers(self) -> Dict[str, str]: + return {'Authorization': f'Bearer {await self.access_token()}'} + + async def access_token(self) -> str: if self._access_token is None or self._access_token.expired(): self._access_token = await self._get_access_token() - return {'Authorization': f'Bearer {self._access_token.token}'} + return self._access_token.token async def _get_access_token(self) -> GoogleExpiringAccessToken: raise NotImplementedError @@ -137,7 +161,7 @@ def __str__(self): async def _get_access_token(self) -> GoogleExpiringAccessToken: now = int(time.time()) - scope = 'openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/compute' + scope = ' '.join(self._scopes) assertion = { "aud": "https://www.googleapis.com/oauth2/v4/token", "iat": now, diff --git a/hail/python/hailtop/aiocloud/common/credentials.py b/hail/python/hailtop/aiocloud/common/credentials.py index 0d703760de8..08fb314e722 100644 --- a/hail/python/hailtop/aiocloud/common/credentials.py +++ b/hail/python/hailtop/aiocloud/common/credentials.py @@ -3,16 +3,12 @@ class CloudCredentials(abc.ABC): - @staticmethod - def from_file(credentials_file): - raise NotImplementedError - - @staticmethod - def default_credentials(): + @abc.abstractmethod + async def auth_headers(self) -> Dict[str, str]: raise NotImplementedError @abc.abstractmethod - async def auth_headers(self) -> Dict[str, str]: + async def access_token(self) -> str: raise NotImplementedError @abc.abstractmethod @@ -20,7 +16,7 @@ async def close(self): raise NotImplementedError -class AnonymousCloudCredentials(CloudCredentials): +class AnonymousCloudCredentials: async def auth_headers(self) -> Dict[str, str]: return {} diff --git a/hail/python/hailtop/aiocloud/common/session.py b/hail/python/hailtop/aiocloud/common/session.py index dcea86811fc..b329d53cdde 100644 --- a/hail/python/hailtop/aiocloud/common/session.py +++ b/hail/python/hailtop/aiocloud/common/session.py @@ -1,10 +1,10 @@ from types import TracebackType -from typing import Optional, Type, TypeVar, Mapping +from typing import Optional, Type, TypeVar, Mapping, Union import aiohttp import abc from hailtop import httpx from hailtop.utils import retry_transient_errors, RateLimit, RateLimiter -from .credentials import CloudCredentials +from .credentials import CloudCredentials, AnonymousCloudCredentials SessionType = TypeVar('SessionType', bound='BaseSession') @@ -63,12 +63,9 @@ async def close(self) -> None: class Session(BaseSession): - _http_session: httpx.ClientSession - _credentials: CloudCredentials - def __init__(self, *, - credentials: CloudCredentials, + credentials: Union[CloudCredentials, AnonymousCloudCredentials], params: Optional[Mapping[str, str]] = None, http_session: Optional[httpx.ClientSession] = None, **kwargs): diff --git a/hail/python/hailtop/auth/__init__.py b/hail/python/hailtop/auth/__init__.py index 378eee1c576..038c652cb27 100644 --- a/hail/python/hailtop/auth/__init__.py +++ b/hail/python/hailtop/auth/__init__.py @@ -2,10 +2,11 @@ from .tokens import (NotLoggedInError, get_tokens, session_id_encode_to_str, session_id_decode_from_str) from .auth import ( - get_userinfo, hail_credentials, + get_userinfo, hail_credentials, IdentityProvider, copy_paste_login, async_copy_paste_login, async_create_user, async_delete_user, async_get_user, async_logout, async_get_userinfo) +from .flow import AzureFlow, Flow, GoogleFlow __all__ = [ 'NotLoggedInError', @@ -16,10 +17,14 @@ 'async_get_userinfo', 'get_userinfo', 'hail_credentials', + 'IdentityProvider', 'async_copy_paste_login', 'async_logout', 'copy_paste_login', 'sql_config', 'session_id_encode_to_str', - 'session_id_decode_from_str' + 'session_id_decode_from_str', + 'AzureFlow', + 'Flow', + 'GoogleFlow', ] diff --git a/hail/python/hailtop/auth/auth.py b/hail/python/hailtop/auth/auth.py index 6da77af4504..efd18937901 100644 --- a/hail/python/hailtop/auth/auth.py +++ b/hail/python/hailtop/auth/auth.py @@ -1,66 +1,131 @@ -from typing import Optional, Dict, Tuple +from typing import Any, Optional, Dict, Tuple, List +from dataclasses import dataclass +from enum import Enum import os +import json import aiohttp from hailtop import httpx from hailtop.aiocloud.common.credentials import CloudCredentials from hailtop.aiocloud.common import Session -from hailtop.config import get_deploy_config, DeployConfig +from hailtop.aiocloud.aiogoogle import GoogleCredentials +from hailtop.aiocloud.aioazure import AzureCredentials +from hailtop.config import get_deploy_config, DeployConfig, get_user_identity_config_path from hailtop.utils import async_to_blocking, retry_transient_errors -from .tokens import Tokens, get_tokens +from .tokens import get_tokens, Tokens -class HailStoredTokenCredentials(CloudCredentials): - def __init__(self, tokens: Tokens, namespace: Optional[str], authorize_target: bool): - self._tokens = tokens - self._namespace = namespace - self._authorize_target = authorize_target +class IdentityProvider(Enum): + GOOGLE = 'Google' + MICROSOFT = 'Microsoft' - @staticmethod - def from_file(credentials_file: str, *, namespace: Optional[str] = None, authorize_target: bool = True): - return HailStoredTokenCredentials(get_tokens(credentials_file), namespace, authorize_target) + +@dataclass +class IdentityProviderSpec: + idp: IdentityProvider + # Absence of specific oauth credentials means Hail should use latent credentials + oauth2_credentials: Optional[dict] @staticmethod - def default_credentials(*, namespace: Optional[str] = None, authorize_target: bool = True): - return HailStoredTokenCredentials(get_tokens(), namespace, authorize_target) + def from_json(config: Dict[str, Any]): + return IdentityProviderSpec(IdentityProvider(config['idp']), config.get('credentials')) + + +class HailCredentials(CloudCredentials): + def __init__(self, tokens: Tokens, cloud_credentials: Optional[CloudCredentials], namespace: str, authorize_target: bool): + self._tokens = tokens + self._cloud_credentials = cloud_credentials + self._namespace = namespace + self._authorize_target = authorize_target async def auth_headers(self) -> Dict[str, str]: - deploy_config = get_deploy_config() - ns = self._namespace or deploy_config.default_namespace() - return namespace_auth_headers(deploy_config, ns, self._tokens, authorize_target=self._authorize_target) + headers = {} + if self._authorize_target: + token = await self._get_idp_access_token_or_hail_token(self._namespace) + headers['Authorization'] = f'Bearer {token}' + if get_deploy_config().location() == 'external' and self._namespace != 'default': + # We prefer an extant hail token to an access token for the internal auth token + # during development of the idp access token feature because the production auth + # is not yet configured to accept access tokens. This can be changed to always prefer + # an idp access token when this change is in production. + token = await self._get_hail_token_or_idp_access_token('default') + headers['X-Hail-Internal-Authorization'] = f'Bearer {token}' + return headers + + async def access_token(self) -> str: + return await self._get_idp_access_token_or_hail_token(self._namespace) + + async def _get_idp_access_token_or_hail_token(self, namespace: str) -> str: + if self._cloud_credentials is not None: + return await self._cloud_credentials.access_token() + return self._tokens.namespace_token_or_error(namespace) + + async def _get_hail_token_or_idp_access_token(self, namespace: str) -> str: + if self._cloud_credentials is None: + return self._tokens.namespace_token_or_error(namespace) + return self._tokens.namespace_token(namespace) or await self._cloud_credentials.access_token() async def close(self): - pass + if self._cloud_credentials: + await self._cloud_credentials.close() + async def __aenter__(self): + return self -def hail_credentials(*, credentials_file: Optional[str] = None, namespace: Optional[str] = None, authorize_target: bool = True) -> CloudCredentials: - if credentials_file is not None: - return HailStoredTokenCredentials.from_file( - credentials_file, - namespace=namespace, - authorize_target=authorize_target - ) - return HailStoredTokenCredentials.default_credentials( - namespace=namespace, - authorize_target=authorize_target - ) - - -def namespace_auth_headers(deploy_config: DeployConfig, - ns: str, - tokens: Tokens, - authorize_target: bool = True, - ) -> Dict[str, str]: - headers = {} - if authorize_target: - headers['Authorization'] = f'Bearer {tokens.namespace_token_or_error(ns)}' - if deploy_config.location() == 'external' and ns != 'default': - headers['X-Hail-Internal-Authorization'] = f'Bearer {tokens.namespace_token_or_error("default")}' - return headers - - -def deploy_config_and_headers_from_namespace(namespace: Optional[str] = None, *, authorize_target: bool = True) -> Tuple[DeployConfig, Dict[str, str], str]: + async def __aexit__(self, *_) -> None: + await self.close() + + +def hail_credentials( + *, + tokens_file: Optional[str] = None, + namespace: Optional[str] = None, + authorize_target: bool = True +) -> HailCredentials: + tokens = get_tokens(tokens_file) + deploy_config = get_deploy_config() + ns = namespace or deploy_config.default_namespace() + return HailCredentials(tokens, get_cloud_credentials_scoped_for_hail(), ns, authorize_target=authorize_target) + + +def get_cloud_credentials_scoped_for_hail() -> Optional[CloudCredentials]: + scopes: Optional[List[str]] + + spec = load_identity_spec() + if spec is None: + return None + + if spec.idp == IdentityProvider.GOOGLE: + scopes = ['email', 'openid', 'profile'] + if spec.oauth2_credentials is not None: + return GoogleCredentials.from_credentials_data(spec.oauth2_credentials, scopes=scopes) + return GoogleCredentials.default_credentials(scopes=scopes, anonymous_ok=False) + + assert spec.idp == IdentityProvider.MICROSOFT + if spec.oauth2_credentials is not None: + return AzureCredentials.from_credentials_data(spec.oauth2_credentials, scopes=[spec.oauth2_credentials['userOauthScope']]) + + if 'HAIL_AZURE_OAUTH_SCOPE' in os.environ: + scopes = [os.environ["HAIL_AZURE_OAUTH_SCOPE"]] + else: + scopes = None + return AzureCredentials.default_credentials(scopes=scopes) + + +def load_identity_spec() -> Optional[IdentityProviderSpec]: + if idp := os.environ.get('HAIL_IDENTITY_PROVIDER_JSON'): + return IdentityProviderSpec.from_json(json.loads(idp)) + + identity_file = get_user_identity_config_path() + if os.path.exists(identity_file): + with open(identity_file, 'r', encoding='utf-8') as f: + return IdentityProviderSpec.from_json(json.loads(f.read())) + + return None + + +async def deploy_config_and_headers_from_namespace(namespace: Optional[str] = None, *, authorize_target: bool = True) -> Tuple[DeployConfig, Dict[str, str], str]: deploy_config = get_deploy_config() if namespace is not None: @@ -68,24 +133,26 @@ def deploy_config_and_headers_from_namespace(namespace: Optional[str] = None, *, else: namespace = deploy_config.default_namespace() - headers = namespace_auth_headers(deploy_config, namespace, get_tokens(), authorize_target=authorize_target) + + async with hail_credentials(namespace=namespace, authorize_target=authorize_target) as credentials: + headers = await credentials.auth_headers() return (deploy_config, headers, namespace) async def async_get_userinfo(): deploy_config = get_deploy_config() - credentials = hail_credentials() userinfo_url = deploy_config.url('auth', '/api/v1alpha/userinfo') - async with Session(credentials=credentials) as session: - try: - async with await session.get(userinfo_url) as resp: - return await resp.json() - except aiohttp.ClientResponseError as err: - if err.status == 401: - return None - raise + async with hail_credentials() as credentials: + async with Session(credentials=credentials) as session: + try: + async with await session.get(userinfo_url) as resp: + return await resp.json() + except aiohttp.ClientResponseError as err: + if err.status == 401: + return None + raise def get_userinfo(): @@ -97,7 +164,7 @@ def copy_paste_login(copy_paste_token: str, namespace: Optional[str] = None): async def async_copy_paste_login(copy_paste_token: str, namespace: Optional[str] = None): - deploy_config, headers, namespace = deploy_config_and_headers_from_namespace(namespace, authorize_target=False) + deploy_config, headers, namespace = await deploy_config_and_headers_from_namespace(namespace, authorize_target=False) async with httpx.client_session(headers=headers) as session: data = await retry_transient_errors( session.post_read_json, @@ -117,6 +184,7 @@ async def async_copy_paste_login(copy_paste_token: str, namespace: Optional[str] return namespace, username +# TODO Logging out should revoke the refresh token and delete the credentials file async def async_logout(): deploy_config = get_deploy_config() @@ -141,7 +209,7 @@ def get_user(username: str, namespace: Optional[str] = None) -> dict: async def async_get_user(username: str, namespace: Optional[str] = None) -> dict: - deploy_config, headers, _ = deploy_config_and_headers_from_namespace(namespace) + deploy_config, headers, _ = await deploy_config_and_headers_from_namespace(namespace) async with httpx.client_session( timeout=aiohttp.ClientTimeout(total=30), @@ -162,7 +230,7 @@ async def async_create_user( *, namespace: Optional[str] = None ): - deploy_config, headers, _ = deploy_config_and_headers_from_namespace(namespace) + deploy_config, headers, _ = await deploy_config_and_headers_from_namespace(namespace) body = { 'login_id': login_id, @@ -187,7 +255,7 @@ def delete_user(username: str, namespace: Optional[str] = None): async def async_delete_user(username: str, namespace: Optional[str] = None): - deploy_config, headers, _ = deploy_config_and_headers_from_namespace(namespace) + deploy_config, headers, _ = await deploy_config_and_headers_from_namespace(namespace) async with httpx.client_session( timeout=aiohttp.ClientTimeout(total=300), headers=headers) as session: diff --git a/hail/python/hailtop/auth/flow.py b/hail/python/hailtop/auth/flow.py new file mode 100644 index 00000000000..1032fa9fc00 --- /dev/null +++ b/hail/python/hailtop/auth/flow.py @@ -0,0 +1,207 @@ +import abc +import base64 +from cryptography import x509 +from cryptography.hazmat.primitives import serialization +import json +import logging +import urllib.parse +from typing import Any, Dict, List, Mapping, Optional, TypedDict, ClassVar + +import aiohttp.web +import google.auth.transport.requests +import google.oauth2.id_token +import google_auth_oauthlib.flow +import jwt +import msal + +from hailtop import httpx +from hailtop.utils import retry_transient_errors + +log = logging.getLogger('auth') + + +class FlowResult: + def __init__(self, login_id: str, email: str, token: Mapping[Any, Any]): + self.login_id = login_id + self.email = email + self.token = token + + +class Flow(abc.ABC): + @abc.abstractmethod + def initiate_flow(self, redirect_uri: str) -> dict: + """ + Initiates the OAuth2 flow. Usually run in response to a user clicking a login button. + The returned dict should be stored in a secure session so that the server can + identify to which OAuth2 flow a client is responding. In particular, the server must + pass this dict to :meth:`.receive_callback` in the OAuth2 callback. + """ + raise NotImplementedError + + @abc.abstractmethod + def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> FlowResult: + """Concludes the OAuth2 flow by returning the user's identity and credentials.""" + raise NotImplementedError + + @staticmethod + @abc.abstractmethod + def perform_installed_app_login_flow(oauth2_client: Dict[str, Any]) -> Dict[str, Any]: + """Performs an OAuth2 flow for credentials installed on the user's machine.""" + raise NotImplementedError + + @staticmethod + @abc.abstractmethod + async def get_identity_uid_from_access_token(session: httpx.ClientSession, access_token: str, *, oauth2_client: dict) -> Optional[str]: + """ + Validate a user-provided access token. If the token is valid, return the identity + to which it belongs. If it is not valid, return None. + """ + raise NotImplementedError + + +class GoogleFlow(Flow): + scopes: ClassVar[List[str]] = [ + 'https://www.googleapis.com/auth/userinfo.profile', + 'https://www.googleapis.com/auth/userinfo.email', + 'openid', + ] + + def __init__(self, credentials_file: str): + self._credentials_file = credentials_file + + def initiate_flow(self, redirect_uri: str) -> dict: + flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( + self._credentials_file, scopes=GoogleFlow.scopes, state=None + ) + flow.redirect_uri = redirect_uri + authorization_url, state = flow.authorization_url(access_type='offline', include_granted_scopes='true') + + return { + 'authorization_url': authorization_url, + 'redirect_uri': redirect_uri, + 'state': state, + } + + def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> FlowResult: + flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( + self._credentials_file, scopes=GoogleFlow.scopes, state=flow_dict['state'] + ) + flow.redirect_uri = flow_dict['callback_uri'] + flow.fetch_token(code=request.query['code']) + token = google.oauth2.id_token.verify_oauth2_token( + flow.credentials.id_token, google.auth.transport.requests.Request() # type: ignore + ) + email = token['email'] + return FlowResult(email, email, token) + + @staticmethod + def perform_installed_app_login_flow(oauth2_client: Dict[str, Any]) -> Dict[str, Any]: + flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_config(oauth2_client, GoogleFlow.scopes) + credentials = flow.run_local_server() + return { + 'client_id': credentials.client_id, + 'client_secret': credentials.client_secret, + 'refresh_token': credentials.refresh_token, + 'type': 'authorized_user', + } + + + @staticmethod + async def get_identity_uid_from_access_token(session: httpx.ClientSession, access_token: str, *, oauth2_client: dict) -> Optional[str]: + oauth2_client_audience = oauth2_client['installed']['client_id'] + try: + userinfo = await retry_transient_errors( + session.get_read_json, + 'https://www.googleapis.com/oauth2/v3/tokeninfo', + params={'access_token': access_token}, + ) + is_human_with_hail_audience = userinfo['aud'] == oauth2_client_audience + is_service_account = userinfo['aud'] == userinfo['sub'] + if not (is_human_with_hail_audience or is_service_account): + return None + + email = userinfo['email'] + if email.endswith('iam.gserviceaccount.com'): + return userinfo['sub'] + # We don't currently track user's unique GCP IAM ID (sub) in the database, just their email, + # but we should eventually use the sub as that is guaranteed to be unique to the user. + return email + except httpx.ClientResponseError as e: + if e.status in (400, 401): + return None + raise + + +class AadJwk(TypedDict): + kid: str + x5c: List[str] + + +class AzureFlow(Flow): + _aad_keys: Optional[List[AadJwk]] = None + + def __init__(self, credentials_file: str): + with open(credentials_file, encoding='utf-8') as f: + data = json.loads(f.read()) + + tenant_id = data['tenant'] + authority = f'https://login.microsoftonline.com/{tenant_id}' + self._client = msal.ConfidentialClientApplication(data['appId'], data['password'], authority) + self._tenant_id = tenant_id + + def initiate_flow(self, redirect_uri: str) -> dict: + flow = self._client.initiate_auth_code_flow(scopes=[], redirect_uri=redirect_uri) + return { + 'flow': flow, + 'authorization_url': flow['auth_uri'], + 'state': flow['state'], + } + + def receive_callback(self, request: aiohttp.web.Request, flow_dict: dict) -> FlowResult: + query_key_to_list_of_values = urllib.parse.parse_qs(request.query_string) + query_dict = {k: v[0] for k, v in query_key_to_list_of_values.items()} + + token = self._client.acquire_token_by_auth_code_flow(flow_dict['flow'], query_dict) + + if 'error' in token: + raise ValueError(token) + + tid = token['id_token_claims']['tid'] + if tid != self._tenant_id: + raise ValueError('invalid tenant id') + + return FlowResult(token['id_token_claims']['oid'], token['id_token_claims']['preferred_username'], token) + + @staticmethod + def perform_installed_app_login_flow(oauth2_client: Dict[str, Any]) -> Dict[str, Any]: + tenant_id = oauth2_client['tenant'] + authority = f'https://login.microsoftonline.com/{tenant_id}' + app = msal.PublicClientApplication(oauth2_client['appId'], authority=authority) + credentials = app.acquire_token_interactive([oauth2_client['userOauthScope']]) + return {**oauth2_client, 'refreshToken': credentials['refresh_token']} + + @staticmethod + async def get_identity_uid_from_access_token(session: httpx.ClientSession, access_token: str, *, oauth2_client: dict) -> Optional[str]: + audience = oauth2_client['appIdentifierUri'] + + try: + kid = jwt.get_unverified_header(access_token)['kid'] + + if AzureFlow._aad_keys is None: + resp = await session.get_read_json('https://login.microsoftonline.com/common/discovery/keys') + AzureFlow._aad_keys = resp['keys'] + + # This code is taken nearly verbatim from + # https://github.com/AzureAD/microsoft-authentication-library-for-python/issues/147 + # At time of writing, the community response in that issue is the recommended way to validate + # AAD access tokens in python as it is not a part of the MSAL library. + + jwk = next(key for key in AzureFlow._aad_keys if key['kid'] == kid) + der_cert = base64.b64decode(jwk['x5c'][0]) + cert = x509.load_der_x509_certificate(der_cert) + pem_key = cert.public_key().public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo).decode() + + decoded = jwt.decode(access_token, pem_key, algorithms=['RS256'], audience=audience) + return decoded['oid'] + except jwt.InvalidTokenError: + return None diff --git a/hail/python/hailtop/auth/tokens.py b/hail/python/hailtop/auth/tokens.py index 516bfa94499..db198e20655 100644 --- a/hail/python/hailtop/auth/tokens.py +++ b/hail/python/hailtop/auth/tokens.py @@ -68,6 +68,9 @@ def __setitem__(self, key: str, value: str): def __getitem__(self, key: str) -> str: return self._tokens[key] + def namespace_token(self, ns: str) -> Optional[str]: + return self._tokens.get(ns) + def namespace_token_or_error(self, ns: str) -> str: if ns in self._tokens: return self._tokens[ns] diff --git a/hail/python/hailtop/batch_client/aioclient.py b/hail/python/hailtop/batch_client/aioclient.py index 7cfe64c5890..922fdf93913 100644 --- a/hail/python/hailtop/batch_client/aioclient.py +++ b/hail/python/hailtop/batch_client/aioclient.py @@ -836,6 +836,9 @@ def __init__(self, token: str): async def auth_headers(self) -> Dict[str, str]: return {'Authorization': f'Bearer {self._token}'} + async def access_token(self) -> str: + return self._token + async def close(self): pass @@ -857,7 +860,7 @@ async def create(billing_project: str, if _token is not None: credentials = HailExplicitTokenCredentials(_token) else: - credentials = hail_credentials(credentials_file=token_file) + credentials = hail_credentials(tokens_file=token_file) return BatchClient( billing_project=billing_project, url=url, diff --git a/hail/python/hailtop/config/__init__.py b/hail/python/hailtop/config/__init__.py index e8103674845..b4f1a842e0e 100644 --- a/hail/python/hailtop/config/__init__.py +++ b/hail/python/hailtop/config/__init__.py @@ -1,4 +1,4 @@ -from .user_config import (get_user_config, get_user_config_path, +from .user_config import (get_user_config, get_user_config_path, get_user_identity_config_path, get_remote_tmpdir, configuration_of) from .deploy_config import get_deploy_config, DeployConfig from .variables import ConfigVariable @@ -7,6 +7,7 @@ 'get_deploy_config', 'get_user_config', 'get_user_config_path', + 'get_user_identity_config_path', 'get_remote_tmpdir', 'DeployConfig', 'ConfigVariable', diff --git a/hail/python/hailtop/config/deploy_config.py b/hail/python/hailtop/config/deploy_config.py index 1bf87ad8052..bd3eb4c139c 100644 --- a/hail/python/hailtop/config/deploy_config.py +++ b/hail/python/hailtop/config/deploy_config.py @@ -9,17 +9,19 @@ log = logging.getLogger('deploy_config') -def env_var_or_default(name: str, default: str) -> str: - return os.environ.get(f'HAIL_{name}') or default +def env_var_or_default(name: str, defaults: Dict[str, str]) -> str: + return os.environ.get(f'HAIL_{name.upper()}') or defaults[name] class DeployConfig: @staticmethod - def from_config(config) -> 'DeployConfig': + def from_config(config: Dict[str, str]) -> 'DeployConfig': + if 'domain' not in config: + config['domain'] = 'hail.is' return DeployConfig( - env_var_or_default('LOCATION', config['location']), - env_var_or_default('DEFAULT_NAMESPACE', config['default_namespace']), - env_var_or_default('DOMAIN', config.get('domain') or 'hail.is') + env_var_or_default('location', config), + env_var_or_default('default_namespace', config), + env_var_or_default('domain', config) ) def get_config(self) -> Dict[str, str]: diff --git a/hail/python/hailtop/config/user_config.py b/hail/python/hailtop/config/user_config.py index 208d02674cf..5f1f2388f18 100644 --- a/hail/python/hailtop/config/user_config.py +++ b/hail/python/hailtop/config/user_config.py @@ -17,8 +17,16 @@ def xdg_config_home() -> Path: return Path(value) +def get_hail_config_path(*, _config_dir: Optional[str] = None) -> Path: + return Path(_config_dir or xdg_config_home(), 'hail') + + def get_user_config_path(*, _config_dir: Optional[str] = None) -> Path: - return Path(_config_dir or xdg_config_home(), 'hail', 'config.ini') + return Path(get_hail_config_path(_config_dir=_config_dir), 'config.ini') + + +def get_user_identity_config_path() -> Path: + return Path(get_hail_config_path(), 'identity.json') def get_user_config() -> configparser.ConfigParser: diff --git a/hail/python/hailtop/hailctl/auth/login.py b/hail/python/hailtop/hailctl/auth/login.py index ece369f3beb..ab39dbd1c00 100644 --- a/hail/python/hailtop/hailctl/auth/login.py +++ b/hail/python/hailtop/hailctl/auth/login.py @@ -1,91 +1,31 @@ -import os -import socket -import asyncio -import json -import webbrowser -from aiohttp import web - from typing import Optional +import json +from hailtop.config import get_deploy_config, DeployConfig, get_user_identity_config_path +from hailtop.auth import hail_credentials, IdentityProvider, AzureFlow, GoogleFlow +from hailtop.httpx import client_session, ClientSession -from hailtop.config import get_deploy_config -from hailtop.auth import get_tokens, hail_credentials -from hailtop.httpx import client_session - - -routes = web.RouteTableDef() - - -@routes.get('/oauth2callback') -async def callback(request): - q = request.app['q'] - code = request.query['code'] - await q.put(code) - # FIXME redirect a nice page like auth.hail.is/hailctl/authenciated with link to more information - return web.Response(text='hailctl is now authenticated.') - - -async def start_server(): - app = web.Application() - app['q'] = asyncio.Queue() - app.add_routes(routes) - runner = web.AppRunner(app) - await runner.setup() - - sock = socket.socket() - sock.bind(("127.0.0.1", 0)) - sock.listen(128) - _, port = sock.getsockname() - site = web.SockSite(runner, sock, shutdown_timeout=0) - await site.start() - - return (runner, port) - - -async def auth_flow(deploy_config, default_ns, session): - runner, port = await start_server() - - async with session.get(deploy_config.url('auth', '/api/v1alpha/login'), params={'callback_port': port}) as resp: - json_resp = await resp.json() - - flow = json_resp['flow'] - state = json_resp['state'] - authorization_url = flow['authorization_url'] - - print( - f''' -Visit the following URL to log into Hail: - - {authorization_url} - -Opening in your browser. -''' - ) - webbrowser.open(authorization_url) - code = await runner.app['q'].get() - await runner.cleanup() +async def auth_flow(deploy_config: DeployConfig, default_ns: str, session: ClientSession): + resp = await session.get_read_json(deploy_config.url('auth', '/api/v1alpha/oauth2-client')) + idp = IdentityProvider(resp['idp']) + client_secret_config = resp['oauth2_client'] + if idp == IdentityProvider.GOOGLE: + credentials = GoogleFlow.perform_installed_app_login_flow(client_secret_config) + else: + assert idp == IdentityProvider.MICROSOFT + credentials = AzureFlow.perform_installed_app_login_flow(client_secret_config) - async with session.get( - deploy_config.url('auth', '/api/v1alpha/oauth2callback'), - params={ - 'callback_port': port, - 'code': code, - 'state': state, - 'flow': json.dumps(flow), - }, - ) as resp: - json_resp = await resp.json() - token = json_resp['token'] - username = json_resp['username'] + with open(get_user_identity_config_path(), 'w', encoding='utf-8') as f: + f.write(json.dumps({'idp': idp.value, 'credentials': credentials})) - tokens = get_tokens() - tokens[default_ns] = token - dot_hail_dir = os.path.expanduser('~/.hail') - if not os.path.exists(dot_hail_dir): - os.mkdir(dot_hail_dir, mode=0o700) - tokens.write() + # Confirm that the logged in user is registered with the hail service + async with hail_credentials(namespace=default_ns) as c: + headers_with_auth = await c.auth_headers() + async with client_session(headers=headers_with_auth) as auth_session: + userinfo = await auth_session.get_read_json(deploy_config.url('auth', '/api/v1alpha/userinfo')) + username = userinfo['username'] if default_ns == 'default': print(f'Logged in as {username}.') else: @@ -94,9 +34,8 @@ async def auth_flow(deploy_config, default_ns, session): async def async_login(namespace: Optional[str]): deploy_config = get_deploy_config() - if namespace: - deploy_config = deploy_config.with_default_namespace(namespace) namespace = namespace or deploy_config.default_namespace() - headers = await hail_credentials(namespace=namespace, authorize_target=False).auth_headers() + async with hail_credentials(namespace=namespace, authorize_target=False) as credentials: + headers = await credentials.auth_headers() async with client_session(headers=headers) as session: await auth_flow(deploy_config, namespace, session) diff --git a/hail/python/hailtop/pinned-requirements.txt b/hail/python/hailtop/pinned-requirements.txt index bdcd36b2cf6..600dc7ae90f 100644 --- a/hail/python/hailtop/pinned-requirements.txt +++ b/hail/python/hailtop/pinned-requirements.txt @@ -76,8 +76,11 @@ google-auth==2.22.0 # via # -r hail/hail/python/hailtop/requirements.txt # google-api-core + # google-auth-oauthlib # google-cloud-core # google-cloud-storage +google-auth-oauthlib==0.8.0 + # via -r hail/hail/python/hailtop/requirements.txt google-cloud-core==2.3.3 # via google-cloud-storage google-cloud-storage==2.10.0 @@ -160,7 +163,9 @@ requests==2.31.0 # msrest # requests-oauthlib requests-oauthlib==1.3.1 - # via msrest + # via + # google-auth-oauthlib + # msrest rich==12.6.0 # via -r hail/hail/python/hailtop/requirements.txt rsa==4.9 diff --git a/hail/python/hailtop/requirements.txt b/hail/python/hailtop/requirements.txt index 236cb0d57a7..827a2351478 100644 --- a/hail/python/hailtop/requirements.txt +++ b/hail/python/hailtop/requirements.txt @@ -8,6 +8,7 @@ botocore>=1.20,<2.0 dill>=0.3.6,<0.4 frozenlist>=1.3.1,<2 google-auth>=2.14.1,<3 +google-auth-oauthlib>=0.5.2,<1 google-cloud-storage>=1.25.0 humanize>=1.0.0,<2 janus>=0.6,<1.1 diff --git a/hail/python/pinned-requirements.txt b/hail/python/pinned-requirements.txt index 1f3dac7fdb3..349faaeb1a0 100644 --- a/hail/python/pinned-requirements.txt +++ b/hail/python/pinned-requirements.txt @@ -128,8 +128,13 @@ google-auth==2.22.0 # -c hail/hail/python/hailtop/pinned-requirements.txt # -r hail/hail/python/hailtop/requirements.txt # google-api-core + # google-auth-oauthlib # google-cloud-core # google-cloud-storage +google-auth-oauthlib==0.8.0 + # via + # -c hail/hail/python/hailtop/pinned-requirements.txt + # -r hail/hail/python/hailtop/requirements.txt google-cloud-core==2.3.3 # via # -c hail/hail/python/hailtop/pinned-requirements.txt @@ -303,6 +308,7 @@ requests==2.31.0 requests-oauthlib==1.3.1 # via # -c hail/hail/python/hailtop/pinned-requirements.txt + # google-auth-oauthlib # msrest rich==12.6.0 # via diff --git a/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala b/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala index 2fc57f7265a..7d7497d853c 100644 --- a/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala +++ b/hail/src/main/scala/is/hail/backend/service/ServiceBackend.scala @@ -41,7 +41,6 @@ import scala.collection.JavaConverters._ import scala.collection.mutable class ServiceBackendContext( - @transient val sessionID: String, val billingProject: String, val remoteTmpDir: String, val workerCores: String, @@ -51,8 +50,6 @@ class ServiceBackendContext( val cloudfuseConfig: Array[(String, String, Boolean)], val profile: Boolean ) extends BackendContext with Serializable { - def tokens(): Tokens = - new Tokens(Map((DeployConfig.get.defaultNamespace, sessionID))) } object ServiceBackend { @@ -439,13 +436,9 @@ object ServiceBackendSocketAPI2 { val deployConfig = DeployConfig.fromConfigFile( s"$scratchDir/secrets/deploy-config/deploy-config.json") DeployConfig.set(deployConfig) - val userTokens = Tokens.fromFile(s"$scratchDir/secrets/user-tokens/tokens.json") - Tokens.set(userTokens) sys.env.get("HAIL_SSL_CONFIG_DIR").foreach(tls.setSSLConfigFromDir(_)) - val sessionId = userTokens.namespaceToken(deployConfig.defaultNamespace) - log.info("Namespace token acquired.") - val batchClient = BatchClient.fromSessionID(sessionId) + val batchClient = new BatchClient(s"$scratchDir/secrets/gsa-key/key.json") log.info("BatchClient allocated.") var batchId = BatchConfig.fromConfigFile(s"$scratchDir/batch-config/batch-config.json").map(_.batchId) @@ -464,7 +457,7 @@ object ServiceBackendSocketAPI2 { log.info("HailContexet initialized.") } - new ServiceBackendSocketAPI2(backend, fs, inputURL, outputURL, sessionId).executeOneCommand() + new ServiceBackendSocketAPI2(backend, fs, inputURL, outputURL).executeOneCommand() } } @@ -570,7 +563,6 @@ class ServiceBackendSocketAPI2( private[this] val fs: FS, private[this] val inputURL: String, private[this] val outputURL: String, - private[this] val sessionId: String, ) extends Thread { private[this] val LOAD_REFERENCES_FROM_DATASET = 1 private[this] val VALUE_TYPE = 2 @@ -689,7 +681,7 @@ class ServiceBackendSocketAPI2( addedSequences.foreach { case (rg, (fastaFile, indexFile)) => ctx.getReference(rg).addSequence(ctx, fastaFile, indexFile) } - ctx.backendContext = new ServiceBackendContext(sessionId, billingProject, remoteTmpDir, workerCores, workerMemory, storageRequirement, regions, cloudfuseConfig, shouldProfile) + ctx.backendContext = new ServiceBackendContext(billingProject, remoteTmpDir, workerCores, workerMemory, storageRequirement, regions, cloudfuseConfig, shouldProfile) method(ctx) } } diff --git a/hail/src/main/scala/is/hail/backend/service/Worker.scala b/hail/src/main/scala/is/hail/backend/service/Worker.scala index d6665c8f405..84c7599dedc 100644 --- a/hail/src/main/scala/is/hail/backend/service/Worker.scala +++ b/hail/src/main/scala/is/hail/backend/service/Worker.scala @@ -111,8 +111,6 @@ object Worker { val deployConfig = DeployConfig.fromConfigFile( s"$scratchDir/secrets/deploy-config/deploy-config.json") DeployConfig.set(deployConfig) - val userTokens = Tokens.fromFile(s"$scratchDir/secrets/user-tokens/tokens.json") - Tokens.set(userTokens) sys.env.get("HAIL_SSL_CONFIG_DIR").foreach(tls.setSSLConfigFromDir(_)) log.info(s"is.hail.backend.service.Worker $myRevision") diff --git a/hail/src/main/scala/is/hail/services/DeployConfig.scala b/hail/src/main/scala/is/hail/services/DeployConfig.scala index e05462e7879..0b5047b868d 100644 --- a/hail/src/main/scala/is/hail/services/DeployConfig.scala +++ b/hail/src/main/scala/is/hail/services/DeployConfig.scala @@ -121,40 +121,4 @@ class DeployConfig( def baseUrl(service: String, baseScheme: String = "http"): String = { s"${ scheme(baseScheme) }://${ domain(service) }${ basePath(service) }" } - - def addresses(service: String, tokens: Tokens = Tokens.get): Seq[(String, Int)] = { - val addressRequester = new Requester(tokens, "address") - implicit val formats: Formats = DefaultFormats - - val addressBaseUrl = baseUrl("address") - val url = s"${addressBaseUrl}/api/${service}" - val addresses = addressRequester.request(new HttpGet(url)) - .asInstanceOf[JArray] - .children - .asInstanceOf[List[JObject]] - addresses.map(x => ((x \ "address").extract[String], (x \ "port").extract[Int])) - } - - def address(service: String, tokens: Tokens = Tokens.get): (String, Int) = { - val serviceAddresses = addresses(service, tokens) - val n = serviceAddresses.length - assert(n > 0) - serviceAddresses(Random.nextInt(n)) - } - - def socket(service: String, tokens: Tokens = Tokens.get): Socket = { - val (host, port) = location match { - case "k8s" | "gce" => - address(service, tokens) - case "external" => - throw new IllegalStateException( - s"Cannot open a socket from an external client to a service.") - } - log.info(s"attempting to connect ${service} at ${host}:${port}") - val s = retryTransientErrors { - getSSLContext.getSocketFactory().createSocket(host, port) - } - log.info(s"connected to ${service} at ${host}:${port}") - s - } } diff --git a/hail/src/main/scala/is/hail/services/Requester.scala b/hail/src/main/scala/is/hail/services/Requester.scala index 3f82bb02d80..082b49c96df 100644 --- a/hail/src/main/scala/is/hail/services/Requester.scala +++ b/hail/src/main/scala/is/hail/services/Requester.scala @@ -6,6 +6,10 @@ import java.nio.charset.StandardCharsets import is.hail.HailContext import is.hail.utils._ import is.hail.services._ +import is.hail.shadedazure.com.azure.identity.{ClientSecretCredential, ClientSecretCredentialBuilder} +import is.hail.shadedazure.com.azure.core.credential.TokenRequestContext + +import com.google.auth.oauth2.ServiceAccountCredentials import org.apache.commons.io.IOUtils import org.apache.http.{HttpEntity, HttpEntityEnclosingRequest} import org.apache.http.client.methods.{HttpDelete, HttpGet, HttpPatch, HttpPost, HttpUriRequest} @@ -19,7 +23,49 @@ import org.apache.log4j.{LogManager, Logger} import org.json4s.{DefaultFormats, Formats, JObject, JValue} import org.json4s.jackson.JsonMethods +import scala.collection.JavaConverters._ import scala.util.Random +import java.io.FileInputStream + + +abstract class CloudCredentials { + def accessToken(): String +} + +class GoogleCloudCredentials(gsaKeyPath: String) extends CloudCredentials { + private[this] val credentials = using(new FileInputStream(gsaKeyPath)) { is => + ServiceAccountCredentials + .fromStream(is) + .createScoped("openid", "email", "profile") + } + + override def accessToken(): String = { + credentials.refreshIfExpired() + credentials.getAccessToken.getTokenValue + } +} + +class AzureCloudCredentials(credentialsPath: String) extends CloudCredentials { + private[this] val credentials: ClientSecretCredential = using(new FileInputStream(credentialsPath)) { is => + implicit val formats: Formats = defaultJSONFormats + val kvs = JsonMethods.parse(is) + val appId = (kvs \ "appId").extract[String] + val password = (kvs \ "password").extract[String] + val tenant = (kvs \ "tenant").extract[String] + + new ClientSecretCredentialBuilder() + .clientId(appId) + .clientSecret(password) + .tenantId(tenant) + .build() + } + + override def accessToken(): String = { + val context = new TokenRequestContext() + context.setScopes(Array(System.getenv("HAIL_AZURE_OAUTH_SCOPE")).toList.asJava) + credentials.getToken(context).block.getToken + } +} class ClientResponseException( val status: Int, @@ -58,14 +104,23 @@ object Requester { .build() } } + + def fromCredentialsFile(credentialsPath: String) = { + val credentials = sys.env.get("HAIL_CLOUD") match { + case Some("gcp") => new GoogleCloudCredentials(credentialsPath) + case Some("azure") => new AzureCloudCredentials(credentialsPath) + case Some(cloud) => + throw new IllegalArgumentException(s"Bad cloud: $cloud") + case None => + throw new IllegalArgumentException(s"HAIL_CLOUD must be set.") + } + new Requester(credentials) + } } class Requester( - tokens: Tokens, - val service: String + val credentials: CloudCredentials ) { - def this(service: String) = this(Tokens.get, service) - import Requester._ def requestWithHandler[T >: Null](req: HttpUriRequest, body: HttpEntity, f: InputStream => T): T = { log.info(s"request ${ req.getMethod } ${ req.getURI }") @@ -73,7 +128,8 @@ class Requester( if (body != null) req.asInstanceOf[HttpEntityEnclosingRequest].setEntity(body) - tokens.addServiceAuthHeaders(service, req) + val token = credentials.accessToken() + req.addHeader("Authorization", s"Bearer $token") retryTransientErrors { using(httpClient.execute(req)) { resp => diff --git a/hail/src/main/scala/is/hail/services/Tokens.scala b/hail/src/main/scala/is/hail/services/Tokens.scala deleted file mode 100644 index def149ff14b..00000000000 --- a/hail/src/main/scala/is/hail/services/Tokens.scala +++ /dev/null @@ -1,69 +0,0 @@ -package is.hail.services - -import is.hail.utils._ -import java.io.{File, FileInputStream} - -import org.apache.http.client.methods.HttpUriRequest -import org.apache.log4j.{LogManager, Logger} -import org.json4s.{DefaultFormats, Formats} -import org.json4s.jackson.JsonMethods - -object Tokens { - private[this] val log: Logger = LogManager.getLogger("Tokens") - - private[this] var _get: Tokens = null - - def set(x: Tokens) = { - _get = x - } - - def get: Tokens = { - if (_get == null) { - val file = getTokensFile() - if (new File(file).isFile) { - _get = fromFile(file) - } else { - log.info(s"tokens file not found: $file") - _get = new Tokens(Map()) - } - } - return _get - } - - def fromFile(file: String): Tokens = { - using(new FileInputStream(file)) { is => - implicit val formats: Formats = DefaultFormats - val tokens = JsonMethods.parse(is).extract[Map[String, String]] - log.info(s"tokens found for namespaces {${ tokens.keys.mkString(", ") }}") - new Tokens(tokens) - } - } - - def getTokensFile(): String = { - val file = System.getenv("HAIL_TOKENS_FILE") - if (file != null) - file - else if (DeployConfig.get.location == "external") - s"${ System.getenv("HOME") }/.hail/tokens.json" - else - "/user-tokens/tokens.json" - } -} - -class Tokens( - tokens: Map[String, String] -) { - def namespaceToken(ns: String): String = tokens(ns) - - def addNamespaceAuthHeaders(ns: String, req: HttpUriRequest): Unit = { - val token = namespaceToken(ns) - req.addHeader("Authorization", s"Bearer $token") - val location = DeployConfig.get.location - if (location == "external" && ns != "default") - req.addHeader("X-Hail-Internal-Authorization", s"Bearer ${ namespaceToken("default") }") - } - - def addServiceAuthHeaders(service: String, req: HttpUriRequest): Unit = { - addNamespaceAuthHeaders(DeployConfig.get.getServiceNamespace(service), req) - } -} diff --git a/hail/src/main/scala/is/hail/services/batch_client/BatchClient.scala b/hail/src/main/scala/is/hail/services/batch_client/BatchClient.scala index 05e0948c2c0..cf1d3f25cff 100644 --- a/hail/src/main/scala/is/hail/services/batch_client/BatchClient.scala +++ b/hail/src/main/scala/is/hail/services/batch_client/BatchClient.scala @@ -5,7 +5,7 @@ import is.hail.expr.ir.ByteArrayBuilder import java.nio.charset.StandardCharsets import is.hail.utils._ import is.hail.services._ -import is.hail.services.{DeployConfig, Tokens} +import is.hail.services.DeployConfig import org.apache.commons.io.IOUtils import org.apache.http.{HttpEntity, HttpEntityEnclosingRequest} import org.apache.http.client.methods.{HttpDelete, HttpGet, HttpPatch, HttpPost, HttpUriRequest} @@ -26,27 +26,14 @@ class NoBodyException(message: String, cause: Throwable) extends Exception(messa object BatchClient { lazy val log: Logger = LogManager.getLogger("BatchClient") - - def fromSessionID(sessionID: String): BatchClient = { - val deployConfig = DeployConfig.get - new BatchClient(deployConfig, - new Tokens(Map( - deployConfig.getServiceNamespace("batch") -> sessionID))) - } } class BatchClient( deployConfig: DeployConfig, requester: Requester ) { - def this() = this(DeployConfig.get, new Requester("batch")) - - def this(deployConfig: DeployConfig) = this(deployConfig, new Requester("batch")) - - def this(tokens: Tokens) = this(DeployConfig.get, new Requester(tokens, "batch")) - def this(deployConfig: DeployConfig, tokens: Tokens) = - this(deployConfig, new Requester(tokens, "batch")) + def this(credentialsPath: String) = this(DeployConfig.get, Requester.fromCredentialsFile(credentialsPath)) import BatchClient._ import requester.request diff --git a/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala b/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala index ca89e8a7498..0ffc1e3dcbc 100644 --- a/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala +++ b/hail/src/test/scala/is/hail/services/batch_client/BatchClientSuite.scala @@ -9,7 +9,7 @@ import org.testng.annotations.Test class BatchClientSuite extends TestNGSuite { @Test def testBasic(): Unit = { - val client = new BatchClient() + val client = new BatchClient("/test-gsa-key/key.json") val token = tokenUrlSafe(32) val batch = client.run( JObject( diff --git a/infra/azure/modules/auth/main.tf b/infra/azure/modules/auth/main.tf index ced783e2727..46eba00e7c4 100644 --- a/infra/azure/modules/auth/main.tf +++ b/infra/azure/modules/auth/main.tf @@ -58,12 +58,53 @@ resource "azuread_application_password" "oauth2" { application_object_id = azuread_application.oauth2.object_id } +resource "random_uuid" "hailctl_oauth2_idenfier_uri_id" {} +resource "random_uuid" "hailctl_oauth2_scope_id" {} + +resource "azuread_application" "hailctl_oauth2" { + display_name = "${var.resource_group_name}-hailctl-oauth2" + + identifier_uris = ["api://hail-${random_uuid.hailctl_oauth2_idenfier_uri_id.result}"] + + public_client { + redirect_uris = ["http://localhost/"] + } + + api { + oauth2_permission_scope { + admin_consent_description = "Allow the Hail library to access the Hail Batch service on behalf of the signed-in user." + admin_consent_display_name = "hailctl" + user_consent_description = "Allow the Hail library to access the Hail Batch service on your behalf." + user_consent_display_name = "hailctl" + enabled = true + id = random_uuid.hailctl_oauth2_scope_id.result + type = "User" + value = "batch.default" + } + } +} + locals { oauth2_credentials = { appId = azuread_application.oauth2.application_id password = azuread_application_password.oauth2.value tenant = data.azurerm_client_config.primary.tenant_id } + + appIdentifierUri = "api://hail-${random_uuid.hailctl_oauth2_idenfier_uri_id.result}" + userOauthScope = "${local.appIdentifierUri}/batch.default" + spOauthScope = "${local.appIdentifierUri}/.default" + + hailctl_oauth2_credentials = { + appId = azuread_application.hailctl_oauth2.application_id + appIdentifierUri = local.appIdentifierUri + # For some reason SP client secret authentication refuses scopes that are not .default and this returned a valid token with + # the desired audience. When creating the oauth scope, terraform refused to create a scope that started with a `.` e.g. `.default`, and + # as such was forced to create the scope `batch.default`. Whether this is a bug in the terraform provider or a feature of AAD is unclear. + userOauthScope = local.userOauthScope + spOauthScope = local.spOauthScope + tenant = data.azurerm_client_config.primary.tenant_id + } } resource "kubernetes_secret" "auth_oauth2_client_secret" { @@ -73,5 +114,7 @@ resource "kubernetes_secret" "auth_oauth2_client_secret" { data = { "client_secret.json" = jsonencode(local.oauth2_credentials) + "hailctl_client_secret.json" = jsonencode(local.hailctl_oauth2_credentials) + "sp_oauth_scope" = local.spOauthScope } } diff --git a/monitoring/test/test_monitoring.py b/monitoring/test/test_monitoring.py index 207b87921e6..bfa22a70bce 100644 --- a/monitoring/test/test_monitoring.py +++ b/monitoring/test/test_monitoring.py @@ -16,17 +16,18 @@ async def test_billing_monitoring(): deploy_config = get_deploy_config() monitoring_deploy_config_url = deploy_config.url('monitoring', '/api/v1alpha/billing') - headers = await hail_credentials().auth_headers() - async with client_session() as session: + async with hail_credentials() as credentials: + async with client_session() as session: - async def wait_forever(): - data = None - while data is None: - data = await retry_transient_errors( - session.get_read_json, monitoring_deploy_config_url, headers=headers - ) - await asyncio.sleep(5) - return data + async def wait_forever(): + data = None + while data is None: + headers = await credentials.auth_headers() + data = await retry_transient_errors( + session.get_read_json, monitoring_deploy_config_url, headers=headers + ) + await asyncio.sleep(5) + return data - data = await asyncio.wait_for(wait_forever(), timeout=30 * 60) - assert data['cost_by_service'] is not None, data + data = await asyncio.wait_for(wait_forever(), timeout=30 * 60) + assert data['cost_by_service'] is not None, data diff --git a/notebook/scale-test.py b/notebook/scale-test.py index 8d3979cadb6..ebc83735d68 100644 --- a/notebook/scale-test.py +++ b/notebook/scale-test.py @@ -26,7 +26,8 @@ def get_cookie(session, name): async def run(args, i): - headers = await hail_credentials(authorize_target=False).auth_headers() + async with hail_credentials(authorize_target=False) as credentials: + headers = await credentials.auth_headers() async with client_session() as session: # make sure notebook is up From f76da5ab771627c792cdd0d5cceb47ea039c63e1 Mon Sep 17 00:00:00 2001 From: Michael Franklin <22381693+illusional@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:29:20 +1000 Subject: [PATCH 178/180] Fix dropped change Co-authored-by: John Marshall --- batch/batch/batch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/batch/batch/batch.py b/batch/batch/batch.py index 2f75119b75e..74a10b2a550 100644 --- a/batch/batch/batch.py +++ b/batch/batch/batch.py @@ -64,7 +64,7 @@ def _time_msecs_str(t): 'time_completed': time_completed, 'duration': duration, 'msec_mcpu': record['msec_mcpu'], - 'cost': coalesce(record['cost'], 0), + 'cost': coalesce(record.get('cost'), 0), 'cost_breakdown': record['cost_breakdown'], } From ba7792d5fa886dbe181e1e3163f3325e3b1cc510 Mon Sep 17 00:00:00 2001 From: Michael Franklin <22381693+illusional@users.noreply.github.com> Date: Tue, 19 Sep 2023 08:26:57 +1000 Subject: [PATCH 179/180] Address review feedback for bad merge --- ci/ci/github.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ci/github.py b/ci/ci/github.py index 004972664a3..ca9ff332bdc 100644 --- a/ci/ci/github.py +++ b/ci/ci/github.py @@ -976,7 +976,7 @@ async def _start_deploy(self, db: Database, batch_client: BatchClient, steps=DEP callback=CALLBACK_URL, ) config.build(deploy_batch, self, scope='deploy') - deploy_batch = await deploy_batch.submit() + await deploy_batch.submit() self.deploy_batch = deploy_batch except concurrent.futures.CancelledError: raise From 2b74e6053389921887ef787fb418cae4958d1ba0 Mon Sep 17 00:00:00 2001 From: Michael Franklin <22381693+illusional@users.noreply.github.com> Date: Wed, 20 Sep 2023 06:45:10 +1000 Subject: [PATCH 180/180] Apply review suggestions --- hail/python/hailtop/batch/backend.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/hail/python/hailtop/batch/backend.py b/hail/python/hailtop/batch/backend.py index fb19c249882..a5cc8c730d0 100644 --- a/hail/python/hailtop/batch/backend.py +++ b/hail/python/hailtop/batch/backend.py @@ -798,9 +798,6 @@ async def compile_job(job): print(f'{jid}: {cmd}') print('') - deploy_config = get_deploy_config() - url = deploy_config.external_url('batch', f'/batches/{batch_id}') - if open: webbrowser.open(url) if wait and len(unsubmitted_jobs) > 0: