Chapter 5¶
This is the fifth in a series of notebooks related to astronomy data.
As a continuing example, we will replicate part of the analysis in a recent paper, “Off the beaten path: Gaia reveals GD-1 stars outside of the main stream” by Adrian M. Price-Whelan and Ana Bonaca.
Picking up where we left off, the next step in the analysis is to select candidate stars based on photometry. The following figure from the paper is a color-magnitude diagram for the stars selected based on proper motion:
In red is a theoretical isochrone, showing where we expect the stars in GD-1 to fall based on the metallicity and age of their original globular cluster.
By selecting stars in the shaded area, we can further distinguish the main sequence of GD-1 from younger background stars.
Outline¶
Here are the steps in this notebook:
We’ll reload the candidate stars we identified in the previous notebook.
Then we’ll run a query on the Gaia server that uploads the table of candidates and uses a
JOIN
operation to select photometry data for the candidate stars.We’ll write the results to a file for use in the next notebook.
After completing this lesson, you should be able to
Upload a table to the Gaia server.
Write ADQL queries involving
JOIN
operations.
Installing libraries¶
If you are running this notebook on Colab, you can run the following cell to install Astroquery and a the other libraries we’ll use.
If you are running this notebook on your own computer, you might have to install these libraries yourself.
If you are using this notebook as part of a Carpentries workshop, you should have received setup instructions.
TODO: Add a link to the instructions.
# If we're running on Colab, install libraries
import sys
IN_COLAB = 'google.colab' in sys.modules
if IN_COLAB:
!pip install astroquery astro-gala pyia python-wget
Reloading the data¶
The following cell downloads the data from the previous notebook.
import os
from wget import download
filename = 'gd1_candidates.hdf5'
path = 'https://github.com/AllenDowney/AstronomicalData/raw/main/data/'
if not os.path.exists(filename):
print(download(path+filename))
And we can read it back.
import pandas as pd
candidate_df = pd.read_hdf(filename, 'candidate_df')
candidate_df
is the Pandas DataFrame that contains results from the query in the previous notebook, which selects stars likely to be in GD-1 based on proper motion. It also includes position and proper motion transformed to the ICRS frame.
import matplotlib.pyplot as plt
x = candidate_df['phi1']
y = candidate_df['phi2']
plt.plot(x, y, 'ko', markersize=0.3, alpha=0.3)
plt.xlabel('ra (degree GD1)')
plt.ylabel('dec (degree GD1)');
This is the same figure we saw at the end of the previous notebook. GD-1 is visible against the background stars, but we will be able to see it more clearly after selecting based on photometry data.
Getting photometry data¶
The Gaia dataset contains some photometry data, including the variable bp_rp
, which we used in the original query to select stars with BP - RP color between -0.75 and 2.
Selecting stars with bp-rp
less than 2 excludes many class M dwarf stars, which are low temperature, low luminosity. A star like that at GD-1’s distance would be hard to detect, so if it is detected, it it more likely to be in the foreground.
Now, to select stars with the age and metal richness we expect in GD-1, we will use g - i
color and apparent g
-band magnitude, which are available from the Pan-STARRS survey.
Conveniently, the Gaia server provides data from Pan-STARRS as a table in the same database we have been using, so we can access it by making ADQL queries.
In general, looking up a star from the Gaia catalog and finding the corresponding star in the Pan-STARRS catalog is not easy. This kind of cross matching is not always possible, because a star might appear in one catalog and not the other. And even when both stars are present, there might not be a clear one-to-one relationship between stars in the two catalogs.
Fortunately, smart people have worked on this problem, and the Gaia database includes cross-matching tables that suggest a best neighbor in the Pan-STARRS catalog for many stars in the Gaia catalog.
This document describes the cross matching process. Briefly, it uses a cone search to find possible matches in approximately the right position, then uses attributes like color and magnitude to choose pairs of stars most likely to be identical.
So the hard part of cross-matching has been done for us. However, using the results is a little tricky.
But, it is also an opportunity to learn about one of the most important tools for working with databases: “joining” tables.
In general, a “join” is an operation where you match up records from one table with records from another table using as a “key” a piece of information that is common to both tables, usually some kind of ID code.
In this example:
Stars in the Gaia dataset are identified by
source_id
.Stars in the Pan-STARRS dataset are identified by
obj_id
.
For each candidate star we have selected so far, we have the source_id
; the goal is to find the obj_id
for the same star (we hope) in the Pan-STARRS catalog.
To do that we will:
Make a table that contains the
source_id
for each candidate star and upload the table to the Gaia server;Use the
JOIN
operator to look up eachsource_id
in thegaiadr2.panstarrs1_best_neighbour
table, which contains theobj_id
of the best match for each star in the Gaia catalog; thenUse the
JOIN
operator again to look up eachobj_id
in thepanstarrs1_original_valid
table, which contains the Pan-STARRS photometry data we want.
Let’s start with the first step, uploading a table.
Preparing a table for uploading¶
For each candidate star, we want to find the corresponding row in the gaiadr2.panstarrs1_best_neighbour
table.
In order to do that, we have to:
Write the table in a local file as an XML VOTable, which is a format suitable for transmitting a table over a network.
Write an ADQL query that refers to the uploaded table.
Change the way we submit the job so it uploads the table before running the query.
The first step is not too difficult because Astropy provides a function called writeto
that can write a Table
in XML
.
The documentation of this process is here.
First we have to convert our Pandas DataFrame
to an Astropy Table
.
from astropy.table import Table
candidate_table = Table.from_pandas(candidate_df)
type(candidate_table)
astropy.table.table.Table
To write the file, we can use Table.write
with format='votable'
, as described here.
table = candidate_table[['source_id']]
table.write('candidate_df.xml', format='votable', overwrite=True)
Notice that we select a single column from the table, source_id
.
We could write the entire table to a file, but that would take longer to transmit over the network, and we really only need one column.
This process, taking a structure like a Table
and translating it into a form that can be transmitted over a network, is called serialization.
XML is one of the most common serialization formats. One nice feature is that XML data is plain text, as opposed to binary digits, so you can read the file we just wrote:
!head candidate_df.xml
<?xml version="1.0" encoding="utf-8"?>

<VOTABLE version="1.4" xmlns="http://www.ivoa.net/xml/VOTable/v1.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.ivoa.net/xml/VOTable/v1.4">
<RESOURCE type="results">

<FIELD ID="source_id" datatype="long" name="source_id"/>
<DATA>
<TABLEDATA>

XML is a general format, so different XML files contain different kinds of data. In order to read an XML file, it’s not enough to know that it’s XML; you also have to know the data format, which is called a schema.
In this example, the schema is VOTable; notice that one of the first tags in the file specifies the schema, and even includes the URL where you can get its definition.
So this is an example of a self-documenting format.
A drawback of XML is that it tends to be big, which is why we wrote just the source_id
column rather than the whole table.
The size of the file is about 750 KB, so that’s not too bad.
!ls -lh candidate_df.xml
-rw-rw-r-- 1 downey downey 396K Oct 19 14:48 candidate_df.xml
If you are using Windows, ls
might not work; in that case, try:
!dir candidate_df.xml
Exercise: There’s a gotcha here we want to warn you about. Why do you think we used double brackets to specify the column we wanted? What happens if you use single brackets?
Run these cells to find out.
table = candidate_table[['source_id']]
type(table)
astropy.table.table.Table
column = candidate_table['source_id']
type(column)
astropy.table.column.Column
# writeto(column, 'candidate_df.xml')
Uploading a table¶
The next step is to upload this table to the Gaia server and use it as part of a query.
Here’s the documentation that explains how to run a query with an uploaded table.
In the spirit of incremental development and testing, let’s start with the simplest possible query.
query = """SELECT *
FROM tap_upload.candidate_df
"""
This query downloads all rows and all columns from the uploaded table. The name of the table has two parts: tap_upload
specifies a table that was uploaded using TAP+ (remember that’s the name of the protocol we’re using to talk to the Gaia server).
And candidate_df
is the name of the table, which we get to choose (unlike tap_upload
, which we didn’t get to choose).
Here’s how we run the query:
from astroquery.gaia import Gaia
job = Gaia.launch_job_async(query=query,
upload_resource='candidate_df.xml',
upload_table_name='candidate_df')
Created TAP+ (v1.2.1) - Connection:
Host: gea.esac.esa.int
Use HTTPS: True
Port: 443
SSL Port: 443
Created TAP+ (v1.2.1) - Connection:
Host: geadata.esac.esa.int
Use HTTPS: True
Port: 443
SSL Port: 443
INFO: Query finished. [astroquery.utils.tap.core]
upload_resource
specifies the name of the file we want to upload, which is the file we just wrote.
upload_table_name
is the name we assign to this table, which is the name we used in the query.
And here are the results:
results = job.get_results()
results
| source_id |
|---|
| int64 |
|<PHONE_NUMBER>39440000 |
|<PHONE_NUMBER>26658176 |
|<PHONE_NUMBER>83965568 |
|<PHONE_NUMBER>74983040 |
|<PHONE_NUMBER>10313600 |
|<PHONE_NUMBER>40132864 |
|<PHONE_NUMBER>94387840 |
|<PHONE_NUMBER>31167104 |
|<PHONE_NUMBER>86133376 |
|<PHONE_NUMBER>33854464 |
| ... |
|<PHONE_NUMBER>58264960 |
|<PHONE_NUMBER>86166656 |
|<PHONE_NUMBER>68697600 |
|<PHONE_NUMBER>17818624 |
|<PHONE_NUMBER>80101760 |
|<PHONE_NUMBER>99159168 |
|<PHONE_NUMBER>91187712 |
|<PHONE_NUMBER>24913152 |
|<PHONE_NUMBER>00423168 |
|<PHONE_NUMBER>02815104 |
If things go according to plan, the result should contain the same rows and columns as the uploaded table.
len(candidate_table), len(results)
(7346, 7346)
set(candidate_table['source_id']) == set(results['source_id'])
True
In this example, we uploaded a table and then downloaded it again, so that’s not too useful.
But now that we can upload a table, we can join it with other tables on the Gaia server.
Joining with an uploaded table¶
Here’s the first example of a query that contains a JOIN
clause.
query1 = """SELECT *
FROM gaiadr2.panstarrs1_best_neighbour as best
JOIN tap_upload.candidate_df as candidate_df
ON best.source_id = candidate_df.source_id
"""
Let’s break that down one clause at a time:
SELECT *
means we will download all columns from both tables.FROM gaiadr2.panstarrs1_best_neighbour as best
means that we’ll get the columns from the Pan-STARRS best neighbor table, which we’ll refer to using the short namebest
.JOIN tap_upload.candidate_df as candidate_df
means that we’ll also get columns from the uploaded table, which we’ll refer to using the short namecandidate_df
.ON best.source_id = candidate_df.source_id
specifies that we will usesource_id
to match up the rows from the two tables.
Here’s the documentation of the best neighbor table.
Let’s run the query:
job1 = Gaia.launch_job_async(query=query1,
upload_resource='candidate_df.xml',
upload_table_name='candidate_df')
INFO: Query finished. [astroquery.utils.tap.core]
And get the results.
results1 = job1.get_results()
results1
| source_id | original_ext_source_id | angular_distance | number_of_neighbours | number_of_mates | best_neighbour_multiplicity | gaia_astrometric_params | source_id_2 |
|---|---|---|---|---|---|---|---|
| arcsec | |||||||
| int64 | int64 | float64 | int32 | int16 | int16 | int16 | int64 |
|<PHONE_NUMBER>26658176 |<PHONE_NUMBER>87671349 | 0.053667035895467084 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>26658176 |
|<PHONE_NUMBER>83965568 |<PHONE_NUMBER>28488720 | 0.038810268141577516 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>83965568 |
|<PHONE_NUMBER>74983040 |<PHONE_NUMBER>77657369 | 0.034323028828991076 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>74983040 |
|<PHONE_NUMBER>10313600 |<PHONE_NUMBER>45631930 | 0.04720255413250006 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>10313600 |
|<PHONE_NUMBER>40132864 |<PHONE_NUMBER>22140135 | 0.020304189709964143 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>40132864 |
|<PHONE_NUMBER>74369792 |<PHONE_NUMBER>91279513 | 0.036524626853403054 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>74369792 |
|<PHONE_NUMBER>35496576 |<PHONE_NUMBER>33502136 | 0.036626827820716606 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>35496576 |
|<PHONE_NUMBER>92748672 |<PHONE_NUMBER>54934147 | 0.021178742393378396 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>92748672 |
|<PHONE_NUMBER>19713664 |<PHONE_NUMBER>85893623 | 0.04518820915043015 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>19713664 |
| ... | ... | ... | ... | ... | ... | ... | ... |
|<PHONE_NUMBER>49124608 |<PHONE_NUMBER>55995561 | 0.04235715830001815 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>49124608 |
|<PHONE_NUMBER>61443072 |<PHONE_NUMBER>58538777 | 0.02265249859012977 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>61443072 |
|<PHONE_NUMBER>16802432 |<PHONE_NUMBER>52465656 | 0.03247653009961843 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>16802432 |
|<PHONE_NUMBER>40341760 |<PHONE_NUMBER>17793839 | 0.036064240818025735 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>40341760 |
|<PHONE_NUMBER>58264960 |<PHONE_NUMBER>45933519 | 0.025293237353496898 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>58264960 |
|<PHONE_NUMBER>68697600 |<PHONE_NUMBER>70219774 | 0.02010316001403086 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>68697600 |
|<PHONE_NUMBER>17818624 |<PHONE_NUMBER>06168780 | 0.051264212025836205 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>17818624 |
|<PHONE_NUMBER>80101760 |<PHONE_NUMBER>75897464 | 0.031783740347530905 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>80101760 |
|<PHONE_NUMBER>99159168 |<PHONE_NUMBER>99751795 | 0.04019174830546698 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>99159168 |
|<PHONE_NUMBER>00423168 |<PHONE_NUMBER>75297310 | 0.009242789669513156 | 1 | 0 | 1 | 5 |<PHONE_NUMBER>00423168 |
This table contains all of the columns from the best neighbor table, plus the single column from the uploaded table.
results1.colnames
['source_id',
'original_ext_source_id',
'angular_distance',
'number_of_neighbours',
'number_of_mates',
'best_neighbour_multiplicity',
'gaia_astrometric_params',
'source_id_2']
Because one of the column names appears in both tables, the second instance of source_id
has been appended with the suffix _2
.
The length of the results table is about 2000, which means we were not able to find matches for all stars in the list of candidate_df.
len(results1)
3724
To get more information about the matching process, we can inspect best_neighbour_multiplicity
, which indicates for each star in Gaia how many stars in Pan-STARRS are equally likely matches.
For this kind of data exploration, we’ll convert a column from the table to a Pandas Series
so we can use value_counts
, which counts the number of times each value appears in a Series
, like a histogram.
import pandas as pd
nn = pd.Series(results1['best_neighbour_multiplicity'])
nn.value_counts()
1 3724
dtype: int64
The result shows that 1
is the only value in the Series
, appearing xxx times.
That means that in every case where a match was found, the matching algorithm identified a single neighbor as the most likely match.
Similarly, number_of_mates
indicates the number of other stars in Gaia that match with the same star in Pan-STARRS.
nm = pd.Series(results1['number_of_mates'])
nm.value_counts()
0 3724
dtype: int64
For this set of candidate_df, almost all of the stars we’ve selected from Pan-STARRS are only matched with a single star in the Gaia catalog.
Detail The table also contains number_of_neighbors
which is the number of stars in Pan-STARRS that match in terms of position, before using other critieria to choose the most likely match.
Getting the photometry data¶
The most important column in results1
is original_ext_source_id
which is the obj_id
we will use to look up the likely matches in Pan-STARRS to get photometry data.
The process is similar to what we just did to look up the matches. We will:
Make a table that contains
source_id
andoriginal_ext_source_id
.Write the table to an XML VOTable file.
Write a query that joins the uploaded table with
gaiadr2.panstarrs1_original_valid
and selects the photometry data we want.Run the query using the uploaded table.
Since we’ve done everything here before, we’ll do these steps as an exercise.
Exercise: Select source_id
and original_ext_source_id
from results1
and write the resulting table as a file named external.xml
.
# Solution
table = results1[['source_id', 'original_ext_source_id']]
table.write('external.xml', format='votable', overwrite=True)
Use !head
to confirm that the file exists and contains an XML VOTable.
!head external.xml
<?xml version="1.0" encoding="utf-8"?>

<VOTABLE version="1.4" xmlns="http://www.ivoa.net/xml/VOTable/v1.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.ivoa.net/xml/VOTable/v1.4">
<RESOURCE type="results">

<FIELD ID="source_id" datatype="long" name="source_id" ucd="meta.id;meta.main">
<DESCRIPTION>
Unique Gaia source identifier
</DESCRIPTION>
Exercise: Read the documentation of the Pan-STARRS table and make note of obj_id
, which contains the object IDs we’ll use to find the rows we want.
Write a query that uses each value of original_ext_source_id
from the uploaded table to find a row in gaiadr2.panstarrs1_original_valid
with the same value in obj_id
, and select all columns from both tables.
Suggestion: Develop and test your query incrementally. For example:
Write a query that downloads all columns from the uploaded table. Test to make sure we can read the uploaded table.
Write a query that downloads the first 10 rows from
gaiadr2.panstarrs1_original_valid
. Test to make sure we can access Pan-STARRS data.Write a query that joins the two tables and selects all columns. Test that the join works as expected.
As a bonus exercise, write a query that joins the two tables and selects just the columns we need:
source_id
from the uploaded tableg_mean_psf_mag
fromgaiadr2.panstarrs1_original_valid
i_mean_psf_mag
fromgaiadr2.panstarrs1_original_valid
Hint: When you select a column from a join, you have to specify which table the column is in.
# Solution
query2 = """SELECT *
FROM tap_upload.external as external
"""
# Solution
query2 = """SELECT TOP 10 *
FROM gaiadr2.panstarrs1_original_valid
"""
# Solution
query2 = """SELECT *
FROM gaiadr2.panstarrs1_original_valid as ps
JOIN tap_upload.external as external
ON ps.obj_id = external.original_ext_source_id
"""
# Solution
query2 = """SELECT
external.source_id, ps.g_mean_psf_mag, ps.i_mean_psf_mag
FROM gaiadr2.panstarrs1_original_valid as ps
JOIN tap_upload.external as external
ON ps.obj_id = external.original_ext_source_id
"""
print(query2)
SELECT
external.source_id, ps.g_mean_psf_mag, ps.i_mean_psf_mag
FROM gaiadr2.panstarrs1_original_valid as ps
JOIN tap_upload.external as external
ON ps.obj_id = external.original_ext_source_id
job2 = Gaia.launch_job_async(query=query2,
upload_resource='external.xml',
upload_table_name='external')
INFO: Query finished. [astroquery.utils.tap.core]
results2 = job2.get_results()
results2
| source_id | g_mean_psf_mag | i_mean_psf_mag |
|---|---|---|
| mag | ||
| int64 | float64 | float64 |
|<PHONE_NUMBER>26658176 | 17.8978004455566 | 17.5174007415771 |
|<PHONE_NUMBER>83965568 | 19.2873001098633 | 17.6781005859375 |
|<PHONE_NUMBER>74983040 | 16.9237995147705 | 16.478099822998 |
|<PHONE_NUMBER>10313600 | 19.9242000579834 | 18.3339996337891 |
|<PHONE_NUMBER>40132864 | 16.1515998840332 | 14.6662998199463 |
|<PHONE_NUMBER>74369792 | 16.5223999023438 | 16.1375007629395 |
|<PHONE_NUMBER>35496576 | 14.5032997131348 | 13.9849004745483 |
|<PHONE_NUMBER>92748672 | 16.5174999237061 | 16.0450000762939 |
|<PHONE_NUMBER>19713664 | 20.4505996704102 | 19.5177001953125 |
| ... | ... | ... |
|<PHONE_NUMBER>49124608 | 20.2343997955322 | 18.6518001556396 |
|<PHONE_NUMBER>61443072 | 21.3848991394043 | 20.3076000213623 |
|<PHONE_NUMBER>16802432 | 17.8281002044678 | 17.4281005859375 |
|<PHONE_NUMBER>40341760 | 21.8656997680664 | 19.5223007202148 |
|<PHONE_NUMBER>58264960 | 22.5151996612549 | 19.9743995666504 |
|<PHONE_NUMBER>68697600 | 19.3792991638184 | 17.9923000335693 |
|<PHONE_NUMBER>17818624 | 17.4944000244141 | 16.926700592041 |
|<PHONE_NUMBER>80101760 | 15.3330001831055 | 14.6280002593994 |
|<PHONE_NUMBER>99159168 | 16.4414005279541 | 15.8212003707886 |
|<PHONE_NUMBER>00423168 | 20.8715991973877 | 19.9612007141113 |
Challenge exercise
Do both joins in one query.
There’s an example here you could start with.
Write the data¶
Since we have the data in an Astropy Table
, let’s store it in a FITS file.
filename = 'gd1_photo.fits'
results2.write(filename, overwrite=True)
We can check that the file exists, and see how big it is.
!ls -lh gd1_photo.fits
-rw-rw-r-- 1 downey downey 96K Oct 19 14:49 gd1_photo.fits
At around 175 KB, it is smaller than some of the other files we’ve been working with.
If you are using Windows, ls
might not work; in that case, try:
!dir gd1_photo.fits
Summary¶
In this notebook, we used database JOIN
operations to select photometry data for the stars we’ve identified as candidates to be in GD-1.
In the next notebook, we’ll use this data for a second round of selection, identifying stars that have photometry data consistent with GD-1.
Best practice¶
Use
JOIN
operations to combine data from multiple tables in a databased, using some kind of identifier to match up records from one table with records from another.This is another example of a practice we saw in the previous notebook, moving the computation to the data.


Tillman scores career-high 21 as MSU routs Charleston Southern 94-46
by APEAST LANSING, Mich. (AP) — Xavier Tillman scored a career-high 21 points and grabbed 10 rebounds to help No. 3 Michigan State tune up with a 94-46 win over Charleston Southern on Monday night.
The Spartans (3-1) were without starting forward Aaron Henry, who rolled both ankles in last week’s win over then-No. 12 Seton Hall, in the on-campus game that is part of the Maui Invitational.
Michigan State’s Gabe Brown made his first career start in place of Henry and the sophomore scored a season-high 12 points. Freshman Rocket Watts had a season-high 11 points, making another start in place of injured Joshua Langford.
Cassius Winston added 11 points and eight assists for the Spartans. He told their fans they’re keeping him going while dealing with the death of his brother earlier this month.
The Buccaneers (1-4) have had four straight lopsided losses since opening with a win over Columbia International.
Charleston Southern’s Dontrell Shuler had 15 points and Terence Porter scored 11 points.
The Buccaneers scored first and led for 15 seconds before the Spartans took over. Michigan State led 31-9 midway through the first half before taking a 40-18 lead at halftime.
The Spartans did not let up in the second half, building a 40-plus point lead to help prepare for tougher competition next week in Hawaii at the Maui Invitational.
BIG PICTURE
Charleston Southern: The Big South team took the game to make some money and gain experience against one of the top teams in the country.
Michigan State: Henry’s injury is potentially problematic for a team already without Langford, who is out until at least January with a foot injury.
UP NEXT
Charleston Southern: Faces Southern Utah on Saturday in a neutral-site game.
Michigan State: Plays Virginia Tech on Monday in the Maui Invitational.


Given exercises processes data, fill in the following table at simulations end according to next algorithms:
| Algorithm: (---) | ||||
| Efficiency | ||||
| Throughput | ||||
| Average duration | ||||
| Avg. waiting time | ||||
| Avg. response time | ||||
| Process | Response Time |
Wait Time |
Duration Time |
% CPU |
| P1 | ||||
| P2 | ||||
| P3 | ||||
| P4 | ||||
| P5 |
| Process | Burst duration (CPU) |
Priority | Submission Time |
| P1 | 5 | 2 | 0 |
| P2 | 4 | 4 | 0 |
| P3 | 7 | 1 | 0 |
| P4 | 3 | 9 | 0 |
| P5 | 1 | 5 | 6 |


Segments structures in images based on image features derived from pseudo-canny-edges.
More...
|
| static bool | GetGlobalDefaultDebug () |
| |
| static void | GlobalDefaultDebugOff () |
| |
| static void | GlobalDefaultDebugOn () |
| |
| static void | SetGlobalDefaultDebug (bool debugFlag) |
| |
| static void | GlobalWarningDisplayOn () |
| |
| static void | GlobalWarningDisplayOff () |
| |
| static void | SetGlobalWarningDisplay (bool flag) |
| |
| static bool | GetGlobalWarningDisplay () |
| |
| static double | GetGlobalDefaultCoordinateTolerance () |
| | Access the global tolerance to determine congruent spaces. More...
|
| |
| static void | SetGlobalDefaultCoordinateTolerance (double) |
| | Access the global tolerance to determine congruent spaces. More...
|
| |
| static double | GetGlobalDefaultDirectionTolerance () |
| | Access the global tolerance to determine congruent spaces. More...
|
| |
| static void | SetGlobalDefaultDirectionTolerance (double) |
| | Access the global tolerance to determine congruent spaces. More...
|
| |
| static bool | SetGlobalDefaultThreader (const std::string &threader) |
| | Set/Get the default threader used for process objects. More...
|
| |
| static std::string | GetGlobalDefaultThreader () |
| | Set/Get the default threader used for process objects. More...
|
| |
| static void | SetGlobalDefaultNumberOfThreads (unsigned int n) |
| |
| static unsigned int | GetGlobalDefaultNumberOfThreads () |
| | Set/Get the default threader used for process objects. More...
|
| |
| void | CheckImageMatchingDimension (const Image &image1, const Image &image2, const std::string &image2Name) |
| |
| void | CheckImageMatchingPixelType (const Image &image1, const Image &image2, const std::string &image2Name) |
| |
| void | CheckImageMatchingSize (const Image &image1, const Image &image2, const std::string &image2Name) |
| |
| virtual unsigned long | AddITKObserver (const itk::EventObject &, itk::Command *) |
| |
| virtual itk::ProcessObject * | GetActiveProcess () |
| |
| virtual void | OnActiveProcessDelete () |
| |
| virtual void | onCommandDelete (const itk::simple::Command *cmd) noexcept |
| |
| virtual void | PreUpdate (itk::ProcessObject *p) |
| |
| virtual void | RemoveITKObserver (EventCommand &e) |
| |
| | NonCopyable ()=default |
| |
| | NonCopyable (const NonCopyable &)=delete |
| |
| NonCopyable & | operator= (const NonCopyable &)=delete |
| |
| template<class TImageType > |
| static void | FixNonZeroIndex (TImageType *img) |
| |
| template<class TImageType > |
| static TImageType::ConstPointer | CastImageToITK (const Image &img) |
| |
| template<class TPixelType , unsigned int VImageDimension, unsigned int VLength, template< typename, unsigned int > class TVector> |
| static Image | CastITKToImage (itk::Image< TVector< TPixelType, VLength >, VImageDimension > *img) |
| |
| template<class TImageType > |
| static Image | CastITKToImage (TImageType *img) |
| |
| static const itk::EventObject & | GetITKEventObject (EventEnum e) |
| |
| template<typename T > |
| static std::ostream & | ToStringHelper (std::ostream &os, const T &v) |
| |
| static std::ostream & | ToStringHelper (std::ostream &os, const char &v) |
| |
| static std::ostream & | ToStringHelper (std::ostream &os, const signed char &v) |
| |
| static std::ostream & | ToStringHelper (std::ostream &os, const unsigned char &v) |
| |
Segments structures in images based on image features derived from pseudo-canny-edges.
- IMPORTANT
- The SegmentationLevelSetImageFilter class and the CannySegmentationLevelSetFunction class contain additional information necessary to the full understanding of how to use this filter.
- OVERVIEW
- This class is a level set method segmentation filter. It constructs a speed function which is designed to lock onto edges as detected by a Canny filter.
- The CannySegmentationLevelSetImageFilter can be a tool for refining an existing segmentation, or it can be used to try to segment a region by itself. Like all other level-set based segmentation filters (see SegmentationLevelSetImageFilter ), it works by first constructing a scalar speed term and a vector advection field based on edge features in the image. The level set front is then moved according to these two terms with the addition of a third curvature term to contol the smoothness of the solution.
- The speed term is constructed as the Danielsson distance transform of the Canny edge image, as calculated by the CannyEdgeDetectionImageFilter . This scalar speed can be tuned in and out of the final evolution equation by setting the PropagationScaling parameter (a value of 0 removes the speed term).
- The advection field term is constructed by minimizing Danielsson distance squared. i.e. \( \mbox{min} \int D^2 \Rightarrow D \nabla D \) . This term moves the level set down the gradient of the distance transform.
- In practice, you may set the speed (propagation) term to zero if your initialization is already close to the edge you are interested in. If you are trying to segment a region by seeding with a small surface (blob, sphere) then you will likely want to add speed (propagation) to the equation so that the levelsets can expand along zero gradients. The relative influence of these two terms are controlled by the SetPropagationScaling and SetAdvectionScaling parameters.
- INPUTS
- This filter requires two inputs. The first input is a seed image. This seed image must contain an isosurface that you want to use as the seed for your segmentation. It can be a binary, graylevel, or floating point image. The only requirement is that it contain a closed isosurface that you will identify as the seed by setting the IsosurfaceValue parameter of the filter. For a binary image you will want to set your isosurface value halfway between your on and off values (i.e. for 0's and 1's, use an isosurface value of 0.5).
- The second input is the feature image. This is the image from which the speed function will be calculated. For most applications, this is the image that you want to segment. The desired isosurface in your seed image should lie within the region of your feature image that you are trying to segment.
- See SegmentationLevelSetImageFilter for more information on Inputs.
- OUTPUTS
- The filter outputs a single, scalar, real-valued image. Positive *values in the output image are inside the segmented region and negative *values in the image are outside of the inside region. The zero crossings of *the image correspond to the position of the level set front.
- See SparseFieldLevelSetImageFilter and SegmentationLevelSetImageFilter for more information.
- PARAMETERS
- There are five parameters important for controlling the behavior of this filter.
- (1) Threshold. Sets the thresholding value of the Canny edge detection. See CannyEdgeDetectionImageFilter for more information.
- (2) Variance. Controls the smoothing parameter of the gaussian filtering done during Canny edge detection.
- (3) CurvatureScaling. Controls the degree to which curvature influences the evolution of the level set. Higher values relative to Propagation and Advection scalings will yield a smoother surface.
- (4) PropagationScaling. Scales the propagation (speed) term of the level set equation. Set this term to zero to allow the level set to flow only down the gradient of the distance transform.
- (5) AdvectionScaling. Scales influence of the advection field relative to curvature and propagation terms.
- See also
- SegmentationLevelSetImageFilter
-
CannySegmentationLevelSetFunction ,
-
SparseFieldLevelSetImageFilter
-
itk::simple::CannySegmentationLevelSet for the procedural interface
-
itk::CannySegmentationLevelSetImageFilter for the Doxygen on the original ITK class.
Definition at line 116 of file sitkCannySegmentationLevelSetImageFilter.h.


The app designed to get you the help you need, when you need it. If you have question, issues, or inquiries related to programing or Lambda School post it here and we will assist.
DevDesk Queue helps you stay organized by keeping tabs on all of your issues. You can create tickets and an administrator will be able to help you out as soon as they can get to it.
With DevDesk Queue, you will be able to submit tickets and get the help you need, when you need it. No more having to go out to multiple locations and message multiple people for help. With the ticket system, you will be able to get help in the fastest time.


species plant climate distribution extinction functional networks coextinction probability time Fig. different phylogenetic network extinctions {border-style change group interactions models flowers, information model px;} #ffffff;} Ecol. clonal, coextinctions subsequent climatically induced climatic seven number phylogeny animal dispersed; open Mediterranean Science Species wind data driven occurrence pollination predicted tree used using Materials S). effects horizon pollinator similar (see Climate Eurosiberian Lett. following fraction insect lost probabilities px; traits {font-family Evol. Table based evolutionary font-size higher however, networks. present relationships signal GBIF Methods Thuiller approach cascades closed considering double; geographic identity local models. networks, previous provided represented European Press, Research Univ. accuracy analyses analysis analyzed best biotic border-color border-width change. changes combined decrease direct food future given groups included interactions. location loss month network, regional scenarios showing shows solid; species, taxonomic temperature total van vulnerability weighted {font-style {font-weight (bio Change Coextinctions Database Ecological Ecology Europe Flora Intergovernmental LINK M_PL_, Panel Plant Rev. S), Syst. TSS bold coextinctions. colors communities community compared considered courier; database degree disappearing distributions ecological effect em; estimated evidence example, extinct extinctions. fig. function horizon. horizons http://orcid.org/--- orders original patterns plants plus potential predict predicting predictor presence projected proportional pruning pt;} ran resulting results sample score, seed significant similarity species. structure table tip versus


--- layout: default ---
Hello and welcome to my portfolio! Here you can explore my website to get a better understanding of my background, projects, and experience.
I'm an engineer who's passionate about full stack software development and robotics, with experience working in the aerospace industry. I have used the skills I learned minoring in computer science to optimize and automate inefficient processes I encountered in my aerospace job, saving employees countless hours on unnecessary and repetitive tasks. Recently I also completed a software engineering bootcamp to further develop this knowledge and gain experience with modern industry standard tools and practices.
When not at work I often enjoy traveling to other countries and most recently backpacked in Asia for 5 months!