<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 GA4GH IPython Example Notebook
This notebook provides an overview of how to call a the GA4GH reference server from an iPython notebook.  Before running this notebook
Step1:  Great! Now we can run calls to query ReferenceSets, References, Datasets, VariantSets, CallSets, Variants, ReadGroups, ReadGroupSets, & Reads. 
Search methods return generators. Here we will explictly create lists out of these objects to allow us to directly index into the list of instances that the query returned.
Instances have a toJsonDict method that returns a dictionary representation of the object. We'll make use of this to examine the the underlying data structures.
Search/Get ReferenceSets
ReferenceSets are lists of References.  Think of them like the genome version (ie. grch37, hg19).
Step2:  Search/Get References
The References endpoints let you access the DNA sequences that make up the reference genome. The example dataset is from subsets of the first 3 chromosomes
Step3:  In addition to fetching metadata about the reference, you can access the base sequence
Step4:  Search/Get Dataset
Datasets are a collection of related data. In this example, we'll examine a collection of reads and variants.
Step5:  Search/Get VariantSets
VariantSets are a collection of variants and calls that are intended to be analyzed together.
Step6:  Search/Get Callset
Callsets are a collection of genotype calls. Callsets apply to the samples within a dataset.
Step7:  Search/Get Variants
A Variant represents a change in DNA sequence relative to some reference. For example, a variant could represent a SNP or an insertion. You can think of them as a row in a VCF. Variants can be supported by many calls.
Step8:  Search/Get Readgroupsets
A ReadGroupSet is a logical collection of ReadGroups. Typically one ReadGroupSet represents all the reads from one experimental sample.
Step9:  Get ReadGroups
A ReadGroup is a set of reads derived from one physical sequencing process.
Step10:  Get Reads
Each read alignment describes an alignment with additional information about the fragment and the read. A read alignment object is equivalent to a line in a SAM file.
Since there are often many reads, we won't iterate over all of them. Instead we can summerize the query and then output the dictionary representing the last one.
<ASSISTANT_TASK:>
Python Code:
baseURL = "http://localhost:8000"
client = ga4gh.client.HttpClient(baseURL)
Explanation: GA4GH IPython Example Notebook
This notebook provides an overview of how to call a the GA4GH reference server from an iPython notebook.  Before running this notebook:
git clone https://github.com/ga4gh/server.git -b develop
Download the example data (if $scripts/download_data.py$ doens't work, wget https://github.com/ga4gh/server/releases/download/data/ga4gh-example-data-v3.2.tar and tar -xvf in the server/ directory
Launch an instance of the reference server on localhost ("python server_dev.py")
Note: If you have trouble importing the ga4gh module, either symlink this notebook into the /server directory or add the path to the GA4GH development repo to your PYTHONPATH.
Connect to GA4GH Server
End of explanation
referenceSets = list(client.searchReferenceSets())
print("ReferenceSets")
for referenceSet in referenceSets:
    print("NCBI Taxon Id: {}".format(referenceSet.ncbiTaxonId))
referenceSet = client.getReferenceSet(referenceSets[0].id)
referenceSet.toJsonDict()
Explanation: Great! Now we can run calls to query ReferenceSets, References, Datasets, VariantSets, CallSets, Variants, ReadGroups, ReadGroupSets, & Reads. 
Search methods return generators. Here we will explictly create lists out of these objects to allow us to directly index into the list of instances that the query returned.
Instances have a toJsonDict method that returns a dictionary representation of the object. We'll make use of this to examine the the underlying data structures.
Search/Get ReferenceSets
ReferenceSets are lists of References.  Think of them like the genome version (ie. grch37, hg19).
End of explanation
references = list(client.searchReferences(referenceSet.id))
print("References")
for reference in references:
    print("Name: {}, Length: {}".format(reference.name, reference.length))
reference = client.getReference(references[0].id)
reference.toJsonDict()
Explanation: Search/Get References
The References endpoints let you access the DNA sequences that make up the reference genome. The example dataset is from subsets of the first 3 chromosomes:
End of explanation
client.listReferenceBases(references[0].id, start=10000, end=10100)
Explanation: In addition to fetching metadata about the reference, you can access the base sequence:
End of explanation
datasets = list(client.searchDatasets())
print("Datasets")
for dataset in datasets:
    print("Name: {}".format(dataset.name))
dataset = client.getDataset(datasets[0].id)
dataset.toJsonDict()
Explanation: Search/Get Dataset
Datasets are a collection of related data. In this example, we'll examine a collection of reads and variants.
End of explanation
variantSets = list(client.searchVariantSets(dataset.id))
print("VariantSets")
for variantSet in variantSets:
    print("Name: {}".format(variantSet.name))
variantSetId = variantSets[0].id
variantSet = client.getVariantSet(variantSetId)
variantSet.toJsonDict()
Explanation: Search/Get VariantSets
VariantSets are a collection of variants and calls that are intended to be analyzed together.
End of explanation
callSets = list(client.searchCallSets(variantSetId))
print("CallSets")
for callSet in callSets:
    print("Name: {}".format(callSet.name))
callSet = client.getCallSet(callSets[0].id)
callSet.toJsonDict()
Explanation: Search/Get Callset
Callsets are a collection of genotype calls. Callsets apply to the samples within a dataset.
End of explanation
variants = list(client.searchVariants(variantSetId, start=100000, end=101000, referenceName = "1"))
print("Variants")
for variant in variants:
    print("Reference Name: {}, Start: {}, Name: {}".format(variant.referenceName, variant.start, variant.names[0]))
variant = client.getVariant(variants[0].id)
variant.toJsonDict()
Explanation: Search/Get Variants
A Variant represents a change in DNA sequence relative to some reference. For example, a variant could represent a SNP or an insertion. You can think of them as a row in a VCF. Variants can be supported by many calls.
End of explanation
readGroupSets = list(client.searchReadGroupSets(dataset.id))
print("ReadGroupSets")
for readGroup in readGroupSets:
    print("Name: {}".format(readGroup.name))
readGroupSet = client.getReadGroupSet(readGroupSets[0].id)
readGroupSet.toJsonDict()
Explanation: Search/Get Readgroupsets
A ReadGroupSet is a logical collection of ReadGroups. Typically one ReadGroupSet represents all the reads from one experimental sample.
End of explanation
readGroup = client.getReadGroup(readGroupSet.readGroups[0].id)
readGroup.toJsonDict()
Explanation: Get ReadGroups
A ReadGroup is a set of reads derived from one physical sequencing process.
End of explanation
readGroupIds = [readGroup.id for readGroup in readGroupSet.readGroups]
readGroupDescriptions = [readGroup.description for readGroup in readGroupSet.readGroups]
reads = client.searchReads(readGroupIds, reference.id)
print("Read Alignments")
# The server paginates reads by default; here we iterate over the reads 
# generate to make the appropriate requests to the server
count = 0
for read in reads:
    count += 1
print("{} reads in Readgroups: {} on Reference: {}".format(
      count, ', '.join(readGroupDescriptions), reference.name))
read.toJsonDict()
Explanation: Get Reads
Each read alignment describes an alignment with additional information about the fragment and the read. A read alignment object is equivalent to a line in a SAM file.
Since there are often many reads, we won't iterate over all of them. Instead we can summerize the query and then output the dictionary representing the last one.
End of explanation
<END_TASK>