Back to catalog
Season 12 12 Episodes 42 min 2026

SunPy: Solar Data Analysis

v7.1 — 2026 Edition. A deep dive into SunPy v7.1 (2026), the community-developed, open-source solar data analysis environment for Python. Master everything from Maps and Coordinates to Fido searches and TimeSeries.

Scientific Computing Solar Physics
SunPy: Solar Data Analysis
Now Playing
Click play to start
0:00
0:00
1
The Core Identity: Quantities and Units
Discover why SunPy mandates physical units for all calculations. Learn how to use Astropy Quantities to prevent critical unit conversion errors in your solar analysis pipeline.
3m 41s
2
The Map Abstraction
Dive into the fundamental data structure of SunPy: the Map. Learn how to ingest FITS files and link 2D data arrays with their underlying observatory metadata.
3m 20s
3
Precision Timing
Master time representation in solar physics using Astropy Time and SunPy TimeRange. Discover why standard Python datetimes fail for high-energy astrophysics.
3m 13s
4
Coordinate Frames and Observers
Learn to navigate the solar surface using Astropy SkyCoord and SunPy's specialized solar frames. Understand the critical role of observer location and observation time.
4m 10s
5
Bridging Pixels and Physical Space
Connect your image pixels to physical coordinates using the World Coordinate System. Learn to flawlessly convert between pixel indices and SkyCoords without manual scaling.
3m 17s
6
Unified Data Search with Fido
Stop writing custom scrapers for every solar archive. Learn how to use Fido to execute complex, unified searches across multiple instruments and wavelengths simultaneously.
3m 24s
7
Deep Queries: JSOC and HEK
Perform advanced queries against the Joint Science Operations Center and the Heliophysics Event Knowledgebase. Retrieve specific event metadata and active region cutouts.
2m 57s
8
Publication-Quality Map Visualization
Transform dim FITS arrays into stunning, publication-ready visualizations. Learn how to configure colormaps, logarithmic normalizations, and clip intervals.
4m 07s
9
Coordinate-Aware Cropping
Safely crop your Maps without corrupting your spatial metadata. Learn why you should use submaps instead of standard NumPy slicing.
3m 18s
10
Aligning and Reprojecting Maps
Combine data from different instruments seamlessly. Learn how to mathematically reproject a map from one coordinate system onto the exact pixel grid of another.
3m 27s
11
1D Temporal Data with TimeSeries
Shift from spatial imagery to temporal lightcurves. Explore the TimeSeries object to load, truncate, and concatenate GOES X-ray flux data.
3m 39s
12
Modeling Differential Rotation
Account for the fluid nature of the solar surface. Learn how to use RotatedSunFrame to predict the future coordinates of an active region as the Sun spins.
3m 34s

Episodes

1

The Core Identity: Quantities and Units

3m 41s

Discover why SunPy mandates physical units for all calculations. Learn how to use Astropy Quantities to prevent critical unit conversion errors in your solar analysis pipeline.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 1 of 12. You might be used to throwing bare numerical arrays into functions and trusting the math to work out. But in solar physics, assuming the dimensions of your data can quietly invalidate your entire analysis pipeline. The safeguard against this is the topic of this episode: The Core Identity: Quantities and Units. If you have tried passing a standard numpy array into a SunPy function, you probably hit an immediate exception. This is not a bug. SunPy intentionally rejects bare numbers. In many scientific domains, a number alone is dangerous. Ten could mean ten degrees, ten arcseconds, or ten meters. If a function mathematically expects radians and you pass degrees, standard Python will happily compute the wrong answer. SunPy prevents this silent failure by requiring explicit unit tracking everywhere in the ecosystem. This is done using Astropy Quantity objects. A Quantity is simply a number, or a full array of numbers, securely bound to a physical unit. You create one by multiplying your raw data by a unit object. For example, you take the number fifteen and multiply it by a unit representing arcseconds. The resulting object carries both pieces of information together. Because Quantity objects are built on top of standard arrays, you can still perform all your usual mathematical operations. You can slice them, compute the mean, or find the maximum value, and the correct unit will stay attached to the result. If you ever need to separate them, you can access the raw number using the dot value attribute, and the unit itself using the dot unit attribute. Usually, you keep them together because the object knows how to handle its own math. If you add meters to kilometers, the Quantity object automatically scales them so the addition is mathematically sound. You can also manually convert between compatible units using the dot to method. Converting meters to kilometers is straightforward because both measure length. But consider a scenario where you need to convert an angular distance measured in the plane of the sky into a physical distance on the surface of the Sun. Strictly speaking, an angle is not a length. By default, the system will block this conversion. Here is the key insight. You can override this strict dimension checking using an equivalency. SunPy provides a specific tool for this called the solar angle equivalency. When you pass this into your conversion method, it supplies the missing physical context. It uses the distance between the observer and the Sun to translate the apparent angle into a literal physical distance, like kilometers across the solar disk. It bridges the gap between observational geometry and physical reality. To enforce this kind of safety in your own code, you use the quantity input decorator. You place this above your function definition to specify what kind of physical dimensions your function accepts. You do not force the user to pass degrees or radians specifically. Instead, you specify that the input must be an angle. If someone tries to pass a unit of time or length, the decorator catches it and throws an error before the function even runs. This rigorous tracking of physical dimensions means your code fails loudly when it is mathematically invalid, rather than quietly returning garbage data. If you enjoy these deep dives, you can support the show by searching for DevStoriesEU on Patreon. That is all for this one. Thanks for listening, and keep building!
2

The Map Abstraction

3m 20s

Dive into the fundamental data structure of SunPy: the Map. Learn how to ingest FITS files and link 2D data arrays with their underlying observatory metadata.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 2 of 12. A massive two-dimensional array of numbers representing solar pixels is completely useless if you do not know the instrument that captured it, the wavelength, or the exact date. To do any real science, those pixels must stay permanently fused to their context. This is the exact problem solved by the Map abstraction. A very common mistake is assuming that a SunPy Map is just a convenience wrapper for making plots. It is not. While it certainly can draw images, at its core, a Map is a coordinate-aware data container. It acts as the central glue that prevents you from losing your metadata when you manipulate the underlying pixels. Let us look at how this works in practice. Suppose you have downloaded a FITS file containing an AIA observation at 171 Angstroms. FITS is the standard file format for astronomical data, and it stores both the raw image array and a header full of observation details. To bring this into your environment, you pass your file path into the sunpy dot map dot Map function. This function actually acts as a factory. It reads the file, automatically detects which instrument took the image, and returns a specialized Map object. We will just call our new object my_map. Once you have your Map, the first primary component to explore is the metadata. Solar observatories pack a tremendous amount of detail into the FITS header, and SunPy extracts all of this into an attribute called my_map dot meta. This attribute behaves exactly like a standard Python dictionary. This means you can programmatically read specific keys to drive your analysis. For example, if your script needs to extract the exact observation date, you just access the date key directly from the meta dictionary. SunPy also normalizes many of these header keys, smoothing out the differences between how various solar instruments name their metadata fields. Now, the second piece of this is the image itself. Here is the key insight. The Map object does not try to reinvent how numerical arrays work. The actual pixel data is stored in an attribute called my_map dot data, and this is nothing more than a standard, two-dimensional NumPy array. Because it is just NumPy, you do not need to learn a new syntax to do your mathematical work. If you want to find the absolute brightest spot in your AIA image, you extract my_map dot data and run a standard maximum function over it. You get your raw pixel value instantly. By keeping the meta dictionary and the data array wrapped up tightly together inside a single Map object, SunPy ensures that your physical units and instrument context are never separated from the raw numbers. It provides a single boundary around everything that makes those pixels meaningful. The real power of the Map abstraction is not that it draws the sun, but that it forces the raw image array and the observational context to travel through your codebase as a single, inseparable unit. That is all for this one. Thanks for listening, and keep building!
3

Precision Timing

3m 13s

Master time representation in solar physics using Astropy Time and SunPy TimeRange. Discover why standard Python datetimes fail for high-energy astrophysics.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 3 of 12. Standard Python datetimes do not know what a leap second is. When you are timing high-energy solar transients, a missed second means your data aligns with empty space instead of the peak of the flare. That is why SunPy relies on Precision Timing. Many developers default to using the standard Python datetime module out of habit. Datetime is not a precision tool. It lacks the astrophysical precision and solar time format support required by SunPy. It ignores leap seconds and cannot handle specialized time scales like utime. Instead, SunPy requires you to use Astropy Time objects. To bring your varied data into this strict ecosystem, you use a function called parse time. Parse time acts as a universal translator for timestamps. You pass it a string in almost any format, whether it is an ISO string, a custom formatted date, or a timestamp pulled directly from an old satellite metadata header. It interprets the input and returns a robust Astropy Time object. This is critical because different solar observatories format their clocks differently. Parse time normalizes everything into a standard object that knows exactly where it sits on the universal timeline, factoring in every leap second along the way. Once your individual timestamps are precise, you need to handle durations. Analyzing a solar event requires bounding your data within an observation window. This is the purpose of the Time Range object. A Time Range represents a continuous span between two exact points. You can define it by providing a start time and an end time, but it is often more practical to provide a start time and a duration. Imagine you are setting up an observation window for a solar flare. You create a Time Range by passing a start string, such as the year 2010, month 3, day 4 at ten minutes past midnight. For the second argument, rather than calculating the exact end time yourself, you pass an Astropy unit quantity of four hundred seconds. The Time Range object absorbs those inputs, applies the correct time scale, and establishes a rigid boundary for your event. This is where it gets interesting. Now, you need to analyze the rising and falling phases of that flare, meaning you want to compare the first half of the event to the second half. The Time Range object has a built-in method called split. You call split and specify the integer two. The method instantly calculates the exact midpoint and returns a list containing two new Time Range objects. Your original four-hundred-second window is perfectly divided into two two-hundred-second sub-intervals. There is no manual date math, and absolutely no risk of dropping a fraction of a second during the division. The built-in Python datetime module is meant for scheduling, but an Astropy Time object is a scientific instrument. Your temporal boundaries require the exact same strict unit tracking as your spatial data, and relying on these specialized objects guarantees your windows remain physically accurate across your entire pipeline. That is your lot for this one. Catch you next time!
4

Coordinate Frames and Observers

4m 10s

Learn to navigate the solar surface using Astropy SkyCoord and SunPy's specialized solar frames. Understand the critical role of observer location and observation time.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 4 of 12. You spot a massive flare on the Sun, record its horizontal and vertical coordinates, and send them to a colleague. But their telescope is parked on a satellite trailing halfway behind the Earth, and your coordinate numbers mean absolutely nothing to them. That is because a point on the Sun is not a static dot on a flat grid. Its position depends entirely on where your telescope is parked in the solar system, and exactly what time it is. The way we resolve this ambiguity is through Coordinate Frames and Observers. It is a frequent mistake to define a point on the solar surface by simply passing two numerical values into a variable. You must explicitly name the context. Without providing an observer location and an observation time, a solar coordinate is physically meaningless. The solar system is constantly moving. The Earth orbits, probes drift along their trajectories, and the Sun itself rotates. To safely define a location in this dynamic environment, SunPy uses an object called SkyCoord, inherited from the Astropy library. A SkyCoord acts as a strict container. It takes your raw numbers and binds them to a specific physical frame of reference, forcing you to define both space and time. The most common frame you will encounter is the Helioprojective frame. This frame describes the Sun exactly as it appears to a specific camera lens. It is a two-dimensional projection of a three-dimensional sphere, measured in angles like arcseconds. It essentially measures lines of sight from the observer to the solar disk. Because it is fundamentally tied to the observer's vantage point, creating a Helioprojective coordinate requires you to supply the observer parameter, which defines where the telescope is, and the obstime parameter, which locks in the exact moment the shutter clicked. Contrast that with the HeliographicStonyhurst frame. This is a true three-dimensional coordinate system that uses solar longitude and latitude. It is intrinsic to the Sun but spatially fixed to the solar system layout. The zero-degree longitude line of the HeliographicStonyhurst frame is locked so that it always points directly at Earth. It gives you an absolute physical location on the solar surface rather than a localized viewing angle. Here is where it gets interesting. Let us walk through how you would translate between perspectives. Suppose you have a SkyCoord for that solar flare recorded from Earth using the Helioprojective frame. You want to figure out exactly where a spacecraft orbiting Venus would see that same flare in its own cameras. First, you instantiate your original SkyCoord with the Earth observer, the observation time, and the arcseconds. Next, you retrieve the physical location of Venus. SunPy includes built-in functions to look up planetary trajectories for a given timestamp. Once you have the coordinate for Venus at that exact observation time, you call the transform method on your original Earth coordinate. You pass this method a brand new Helioprojective frame, but you set the observer parameter of this new frame to Venus. SunPy then runs the complex three-dimensional geometry under the hood. It calculates the physical lines of sight and returns a new SkyCoord. This resulting object contains the exact angular coordinates the flare appeared at from the viewpoint of Venus. The most critical insight to take away is that a solar coordinate is never just a location; it is a strict relationship between a target and an observer frozen at a specific millisecond. That is all for this one. Thanks for listening, and keep building!
5

Bridging Pixels and Physical Space

3m 17s

Connect your image pixels to physical coordinates using the World Coordinate System. Learn to flawlessly convert between pixel indices and SkyCoords without manual scaling.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 5 of 12. You have a specific location on the Sun, like an active flare, and you need to extract its exact data values from your image matrix. Translating a spherical physical point in space down to a row and column in a flat matrix usually requires painful trigonometry. Bridging pixels and physical space handles this for you instantly using the World Coordinate System. A SunPy Map is a two-dimensional NumPy array of pixels paired with extensive metadata. This metadata defines where the telescope was pointing, the physical size of each pixel, and the specific spherical projection used to flatten the image. SunPy bundles all these geometric rules into an object accessed via the map's WCS property. WCS stands for World Coordinate System. This object acts as the translation layer between your flat data grid and the physical sky. Here is the key insight. You must keep your coordinate ordering straight depending on which domain you are in. Because the underlying image data is a NumPy array, it expects data access using row then column ordering. That means the y-axis comes before the x-axis. The World Coordinate System operates on physical space, using standard Cartesian geometry where x comes before y. Physical coordinate inputs are ordered x then y. Direct array indexing is ordered y then x. Mixing these up is a frequent source of bugs. Now, let us move from the physical sky to the pixel grid. Suppose you want to find the exact fractional pixel location that corresponds to the physical center of your map. The map provides a property called center. This represents a physical Helioprojective coordinate in space. You can pass that center coordinate directly into the map's world to pixel method. The World Coordinate System processes the projection math and returns an object containing the exact x and y pixel values. These returned values are floating-point numbers. A physical coordinate almost never lands perfectly in the dead center of a discrete integer pixel. That covers moving inward to the data. What about moving outward to the sky? You might find a feature using a computer vision algorithm on your flat array, perhaps at pixel column four hundred and row five hundred. You need to know its actual physical location on the Sun. To do this, you use the map's pixel to world method. You provide the pixel location using Astropy Quantities to define the exact pixel units. The method pushes those pixel values through the reverse math of the World Coordinate System and returns a precise Astropy SkyCoord object. This object tells you exactly where that specific pixel sits in Helioprojective space, complete with proper physical units. The World Coordinate System handles the messy trigonometry of spherical projections so you can stop worrying about raw matrix indices and start analyzing actual physical locations on the solar disk. Thanks for listening. Take care, everyone.
6

Unified Data Search with Fido

3m 24s

Stop writing custom scrapers for every solar archive. Learn how to use Fido to execute complex, unified searches across multiple instruments and wavelengths simultaneously.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 6 of 12. There are dozens of solar observatories and data archives out there, each with its own quirks. Instead of learning ten different web APIs just to find out what observations exist for a specific solar flare, you only need to learn one tool. That tool is Unified Data Search with Fido. Fido stands for Federated Internet Data Obtainer. It acts as a universal translator for solar data APIs, drastically reducing the boilerplate code required to find observations. You give it your scientific parameters, and Fido handles the network requests to multiple data centers behind the scenes. A common misconception is that running a Fido search automatically downloads the data. It does not. The search function strictly returns a metadata table called a UnifiedResponse. This allows you to inspect the number of files, their sizes, and their sources before you commit to transferring anything to your local machine. To perform a search, you use the Fido dot search function. You construct your query by passing it search attributes. In SunPy, these attributes live in the sunpy dot net dot attrs module, which is almost always imported as simply the letter a. Every search requires a time range. You define this using a dot Time, passing it a start string and an end string. From there, you narrow down the results using other attributes, most commonly a dot Instrument. Here is the key insight. Fido allows you to construct complex, multi-instrument queries in a single function call using standard logical operators. Specifically, you use the pipe character to represent a logical OR. Suppose you are analyzing an event and need data covering a specific two hour window. You want observations from either the LYRA instrument or the RHESSI instrument. Without Fido, you would write one API request for LYRA, a completely different request for RHESSI, and then manually merge the resulting JSON responses. With Fido, you build this natively. You define your two hour time window using a dot Time. Then, you define your instrument targets: a dot Instrument with LYRA, and a dot Instrument with RHESSI. You put the pipe character between the two instrument definitions. When you pass this into Fido dot search, you give it the time attribute, a comma, and then your combined instrument attributes grouped in parentheses. Fido reads the pipe operator, splits the request, queries the relevant databases for both instruments over that identical time span, and merges everything back together. The UnifiedResponse you get back is organized intuitively. If your query hit multiple data providers, the results are grouped by provider. You can slice and print this table right in your terminal to see exactly which observatory holds the data you need. The true power of Fido is not just that it finds solar data, but that it normalizes the chaos of scattered archives into one predictable Python syntax. If you would like to help us keep making these episodes, you can support the show by searching for DevStoriesEU on Patreon. That is all for this one. Thanks for listening, and keep building!
7

Deep Queries: JSOC and HEK

2m 57s

Perform advanced queries against the Joint Science Operations Center and the Heliophysics Event Knowledgebase. Retrieve specific event metadata and active region cutouts.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 7 of 12. Sometimes you do not know the exact time a solar event happened. You just want to ask a database to show you all the Coronal Mass Ejections from last month. If you try to pull that directly from an image archive, you will either get millions of files or nothing at all. To bridge the gap between abstract events and actual pixels, we use two specific tools: the Heliophysics Event Knowledgebase, or HEK, and the Joint Science Operations Center, or JSOC. The HEK is a catalog of physical solar phenomena. It records flares, active regions, and coronal mass ejections detected by various algorithms and human observers. Many users query the HEK expecting to receive image files in return. They do not. The HEK returns event metadata. When you search it, you get a data table containing start times, peak times, bounding polygons, and observation notes. To search the HEK, you use the standard Fido search function. You provide a time range, and then you add a specific HEK event attribute. If you are looking for a coronal mass ejection, you pass the HEK CME attribute. The database evaluates this and returns a list of matching events. From that list, you isolate the specific event you want and extract its peak time. You now have a precise temporal coordinate for your phenomenon. With that precise time in hand, you move to the second step: fetching the actual imagery. For detailed Solar Dynamics Observatory data, you query the JSOC. The JSOC is the primary archive for instruments like AIA and HMI. It stores the heavy data series containing the actual pixels. You construct a new Fido search using the peak time you extracted from the HEK. This time, you pass a JSOC Series attribute. This tells the archive exactly which instrument and data product you need. You can refine this further using a JSOC Segment attribute to pull only specific data files, rather than an entire data cube. Here is the key insight. Unlike generic queries, JSOC processes data exports on demand, and it requires user identification. You must include a JSOC Notify attribute containing your registered email address inside your Fido search. If you omit the email address, the query will fail. The JSOC servers queue your request, prepare the exact cut of data you asked for, and stage it for download. By chaining these two systems together, you completely automate the discovery process. You start with a broad timeframe, ask the HEK to pinpoint exactly when a specific event occurred, and pass those precise timestamps to the JSOC to retrieve the raw imagery. The knowledgebase gives you the map, and the operations center gives you the territory. That is all for this one. Thanks for listening, and keep building!
8

Publication-Quality Map Visualization

4m 07s

Transform dim FITS arrays into stunning, publication-ready visualizations. Learn how to configure colormaps, logarithmic normalizations, and clip intervals.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 8 of 12. You load a beautiful piece of solar data, render the image, and end up staring at a totally black square with exactly one bright white pixel in the corner. Your data is fine, but your dynamic range is completely hiding it. Fixing this is what Publication-Quality Map Visualization is all about. When developers first try to visualize a SunPy map, they often pull the raw data array and feed it straight into a standard matplotlib image show command. This renders the pixels, but it drops all physical context. You lose your coordinate system entirely, and your axes default to simple array indices. SunPy resolves this with a built-in plot method directly on the map object. When you call plot on your map, SunPy automatically provisions a World Coordinate System axis, known as a WCS axis. This ensures your tick marks accurately represent physical units on the sky, such as arcseconds. You do not have to abandon matplotlib layouts to use this. You can create a standard matplotlib figure and add a subplot. The trick is to pass the map's WCS object into the projection argument of that subplot. Then, you simply pass that specific axis back into the map's plot method. This integration gives you the precise formatting control of matplotlib while keeping the strict spatial awareness of SunPy. Now, back to that black square with one bright pixel. Solar images have extreme contrast. A solar flare might be tens of thousands of times brighter than the faint coronal loops right next to it. If you map the raw data values linearly to a visual color scale, the flare claims the top end of the scale, and everything else gets crushed into shadow. Here is the key insight. You must compress the dynamic range before rendering. You do this in two steps using clipping and normalization. First, use the clip interval keyword argument in the map's plot method. Instead of letting one ultra-bright outlier define the maximum value of your color scale, you can supply a tuple representing percentiles. Setting the clip interval from one percent to ninety-nine point five percent forces the plot method to ignore the dimmest one percent and the brightest half-percent of pixels when calculating the color boundaries. Clipping instantly cuts through the glare of extreme outliers. Second, even after clipping, a linear scale usually leaves quiet regions too dark. To fix this, import the LogNorm class from matplotlib colors. You pass an instance of LogNorm into the norm keyword of the map plot method. Applying a logarithmic stretch mathematically amplifies the faint structures in the dark regions of the image, while compressing the visual differences in the brighter regions. When you apply LogNorm, those faint, sweeping coronal loops emerge clearly from the background. Finally, set the correct visual palette. SunPy automatically registers standard solar colormaps within matplotlib. By passing the cmap keyword argument to the plot method, you can specify an exact instrument channel. Passing a string like sdoaia171 applies the precise gold-colored palette the scientific community uses for that specific wavelength. Combining the built-in plot method for coordinate accuracy, clip intervals for handling outliers, logarithmic normalization for dynamic range, and an instrument-specific colormap transforms a nearly completely dark array into a detailed, publication-ready scientific figure. I would like to take a moment to thank you for listening — it helps us a lot. Have a great one!
9

Coordinate-Aware Cropping

3m 18s

Safely crop your Maps without corrupting your spatial metadata. Learn why you should use submaps instead of standard NumPy slicing.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 9 of 12. Slicing a NumPy array is fast and easy. But if you do it to a solar image, your spatial coordinates will instantly become garbage. The mechanism that prevents this is Coordinate-Aware Cropping. When Python developers need to isolate a specific active region on a full-disk solar image, their first instinct is often to slice the underlying data array directly. They grab rows zero to one hundred and columns zero to one hundred. This extracts the visual pixels you want, but it completely corrupts the World Coordinate System attached to the file. The metadata still assumes the original image dimensions. Because the WCS relies on a specific reference pixel index to anchor the coordinate grid, slicing the array without updating the header means your pixels no longer map to the correct physical locations on the Sun. Any overlay or measurement you try to make next will fail because the math is out of alignment. To safely extract a region of interest, SunPy provides the submap method. This performs coordinate-aware cropping directly on the map object itself. It ensures the image array and the spatial metadata stay perfectly synchronized at all times. Suppose you want a tight bounding box around a solar flare. Instead of guessing array indices, you define the boundary using physical space. First, you create a coordinate object representing the bottom-left corner of your desired region. You specify the location in physical units, typically arcseconds, and you use the coordinate frame from your original map so everything shares the same origin. Then, you create a second coordinate object for the top-right corner of your box. With those two points defined, you call the submap method on your original map and pass the bottom-left and top-right coordinates as arguments. The method reads the physical bounding box, translates those physical coordinates into exact pixel indices, and slices the data array for you. You never have to calculate the row or column numbers yourself. Here is the key insight. The submap method does not just return a smaller picture. It actively rewrites the WCS header for the new map. It calculates the new position of the reference pixel relative to your cropped dimensions. Even if the original reference pixel was completely outside your new bounding box, the WCS math is automatically adjusted so the coordinate grid remains perfectly accurate. The reference pixel shifts, the array shrinks, and the resulting submap is a fully valid map object that still knows exactly where it sits in the physical universe. If you bypass the map object and slice the raw array, you break the link between your data and the physical sky; always let the submap method handle the coordinate math for you. That is all for this one. Thanks for listening, and keep building!
10

Aligning and Reprojecting Maps

3m 27s

Combine data from different instruments seamlessly. Learn how to mathematically reproject a map from one coordinate system onto the exact pixel grid of another.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 10 of 12. Just because two different instruments take a picture of the Sun at the exact same second does not mean their pixels line up. Overlaying them directly will give you a misaligned mess. Aligning and Reprojecting Maps solves this. When comparing data from the Atmospheric Imaging Assembly, or AIA, and the Helioseismic and Magnetic Imager, or HMI, both instruments sit on the same satellite. They capture images simultaneously. A common mistake is assuming that these two full-disk images can be directly overlaid just because the timing matches. But instruments have different plate scales, meaning their individual pixels cover different physical areas. They also have slight pointing offsets. If you take a high-resolution extreme ultraviolet image from AIA and a lower-resolution magnetogram from HMI, their grids simply do not align. Say you want to plot the magnetic contours from the HMI data perfectly over the coronal loops in the AIA image. To do this, you must cast the HMI data into the World Coordinate System, or WCS, of the AIA map. The WCS is the mathematical framework embedded in the map that translates a pixel location into an actual physical coordinate on the sky. SunPy handles this transformation through an external package called reproject. You use a function named reproject underscore interp. This function performs fast spatial interpolation, which is the necessary approach when you are aligning standard solar imaging data. First, you define your target. In this scenario, the target is the AIA map, so you extract its WCS object. Next, you pass your source map, the HMI magnetogram, and that target WCS into the interpolation function. The function projects the target grid onto the source data. It calculates where the new pixels sit in physical space, queries the original HMI map at those precise coordinates, and interpolates the pixel values. By default, the function hands you back a new raw data array shaped exactly like the target image, alongside a footprint array. The footprint indicates which pixels fell outside the original field of view. Since you only need the data for the overlay, you can pass a parameter to ignore the footprint entirely, which returns just the interpolated array. To make this raw array useful, you construct a new SunPy map. You pair your newly interpolated HMI data array with the metadata header from your target AIA map. Here is the key insight. Reprojection mathematically guarantees identical spatial grids. Your new HMI map now has the exact same dimensions and plate scale as the AIA map. Index five-hundred by five-hundred in the newly aligned map corresponds to the exact same physical solar feature as index five-hundred by five-hundred in the AIA map. You can now plot the AIA image on a set of axes, and confidently draw the magnetic contours from your aligned map directly on top. Because reprojection permanently alters your original data values through interpolation to force a coordinate match, always perform this alignment step last, right before your final visualization or array math. Thanks for spending a few minutes with me. Until next time, take it easy.
11

1D Temporal Data with TimeSeries

3m 39s

Shift from spatial imagery to temporal lightcurves. Explore the TimeSeries object to load, truncate, and concatenate GOES X-ray flux data.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 11 of 12. Solar images are visually stunning, but sometimes the most critical information is just a single scalar flux value measured a thousand times a second. When you track a solar flare's intensity over an entire week, a two-dimensional spatial matrix is simply the wrong tool for the job. You need 1D Temporal Data with TimeSeries. It is a common mistake to reach for the Map object by default when starting with SunPy. But Map is strictly for two-dimensional spatial data. When you are dealing with one-dimensional temporal data—like an X-ray light curve spanning several days across multiple wavelength channels—you use TimeSeries. It acts as the one-dimensional equivalent to Map, designed specifically to handle time-indexed measurements while safely preserving observation metadata and physical units. Under the hood, a TimeSeries object relies on a pandas DataFrame to structure your timestamps and data columns. The problem with working directly in raw pandas is that standard dataframes do not understand scientific units. TimeSeries wraps this data structure to ensure your physical units and instrument metadata remain firmly attached during operations. Consider loading an X-ray light curve from a GOES-15 satellite file. You pass the file path to the TimeSeries function, and it returns an object containing multiple observation channels as columns. You can inspect these columns by name, such as the short-wavelength and long-wavelength channels. Here is the key insight. Instead of extracting raw numerical arrays directly from the underlying dataframe, you extract columns using the quantity method. You call quantity and pass it the specific column name you want. This method returns the data as an Astropy Quantity object. This means the raw numerical flux values are strictly bound to their physical units, like watts per square meter. Extracting data this way completely prevents silent unit conversion errors downstream in your mathematical calculations. Once you have your data loaded, you rarely need the entire observation file. You might only want to isolate the exact hour a solar flare peaked. You achieve this by truncating the TimeSeries. First, you define a TimeRange object by providing a start time string and an end time string. You then pass this TimeRange directly into the truncate method of your TimeSeries. This slices the underlying dataframe and returns a brand new TimeSeries object. The data is cleanly cut down to your exact window of interest, and all the associated metadata survives the cut. Often, your analysis requires data that spans across multiple separate observation files. If your goal is to build a continuous week-long dataset, you load your second file into its own TimeSeries object. Then, you simply call the concatenate method on the first TimeSeries, passing the second one as the argument. SunPy aligns the time indices and merges the data rows. As long as the instrument metadata from both files is compatible, you get back a single, unified TimeSeries object ready for continuous analysis across the extended time frame. When processing temporal data, strictly binding your timestamps and numerical values to their physical units is what separates a reliable scientific analysis from a silent calculation failure. That is all for this one. Thanks for listening, and keep building!
12

Modeling Differential Rotation

3m 34s

Account for the fluid nature of the solar surface. Learn how to use RotatedSunFrame to predict the future coordinates of an active region as the Sun spins.

Download
Hi, this is Alex from DEV STORIES DOT EU. SunPy: Solar Data Analysis, episode 12 of 12. The Sun is not a solid rock. Its equator spins significantly faster than its poles, meaning any coordinate grid you map onto it is slowly tearing itself apart. If you track an active region on Tuesday, those same latitude and longitude values will point to empty space by Thursday. To track the actual plasma, you need a mechanism called Modeling Differential Rotation. People often treat celestial bodies like solid spheres. On Earth, a geographic coordinate stays put. On the Sun, the surface is fluid. Plasma at the solar equator completes a full rotation in about twenty-five days, while plasma near the poles takes over thirty-four days. Because coordinates are inherently time-dependent, you cannot just carry over a spatial position from one day to the next. You have to account for the physical shift of the solar material over time. SunPy handles this time-dependent shift using a coordinate frame called Rotated Sun Frame. This frame lets you take a coordinate measured at an initial time and project where that exact parcel of solar material will be at a new time. Here is the key insight. Rotated Sun Frame acts as a wrapper around an existing coordinate frame. You do not calculate the new latitude and longitude manually. Instead, you define a frame that explicitly encodes the time difference, and you let the coordinate transformation engine do the math. Suppose you have the coordinates for an active region observed on Tuesday. This is your initial point, represented as a SkyCoord object. It has a spatial position and an observation time. To find where that active region will be on Thursday, you set up a new Rotated Sun Frame. First, you provide the base frame, which you extract directly from your Tuesday coordinate. Next, you provide the target time. You can specify Thursday's exact timestamp, or you can pass a duration, like a two-day time delta. SunPy now has a target coordinate frame that understands the solar rotation model. Finally, you take your Tuesday coordinate and transform it into this new Rotated Sun Frame. When you run this transformation, SunPy applies a standard differential rotation profile. It reads the latitude of your starting coordinate, calculates the correct angular velocity for that specific latitude, multiplies it by your two-day duration, and shifts the longitude. The output is a new coordinate object. Its latitude and longitude are updated to reflect two days of differential rotation, pinpointing exactly where your active region plasma has drifted by Thursday. If the region was near the equator, it shifted a large amount. If it was near the pole, it moved much less. This approach allows you to step coordinates forward or backward in time seamlessly. Because differential rotation changes the physical location of the data you are studying, tying every coordinate to a specific observation time and shifting it through the rotation model is the only way to maintain accuracy across multiple observations. This wraps up our series on solar data analysis. I encourage you to explore the official SunPy documentation, try these tools hands-on, or visit devstories dot eu to suggest topics for future series. That is all for this one. Thanks for listening, and keep building!