<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Universe OpenAstronomy (Posts by Racim MENASRIA)</title><link>http://openastronomy.org/Universe_OA/</link><description></description><atom:link href="http://openastronomy.org/Universe_OA/authors/racim-menasria.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Wed, 31 Dec 2025 02:08:37 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Progress on Kurucz and NIST databases</title><link>http://openastronomy.org/Universe_OA/posts/2023/08/20230811_1723_menasrac/</link><dc:creator>Racim MENASRIA</dc:creator><description>&lt;p&gt;Since the last article, I received a lot of feedback and comments about the Kurucz PR.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/952/1*iyB8Ya_dKD5OIkQ8gbcovg.png"&gt;&lt;/figure&gt;&lt;p&gt;Here is and example of a Fe_I spectrum I can obtain with these conditions.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*alxgHx0L0Bg54hyUcp8h0Q.png"&gt;&lt;/figure&gt;&lt;h4&gt;The main remarks where that :&lt;/h4&gt;&lt;p&gt;I needed to adjust the code to make it more general and user friendly. I introduced a specie argument to SpectrumFactory and calc_spectrum to replace atom and molecule and gather them under a same name.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;p&gt;I made sure to respect the Radis structure by mooving files where I needed to and adding a new Partfunc class for Kurucz. &lt;br&gt;Then I added a few tests and removed old tests that were not needed any longer.&lt;/p&gt;
&lt;p&gt;I also cleaned my PR : removed all the unused methods from the Kurucz API,added references, moved hardcoded arrays to proper files.&lt;/p&gt;
&lt;p&gt;We asked the Exojax team for more help about the broadening parameters. For the moment, there are some approximations and placeholders about the airbrd (air broadening which is required in the Radis format) by computing it thanks to the Kurucz parameters.&lt;br&gt;A simplified version of the broadening allows to plot spectra for now but there are still values to adjust for the various species.&lt;/p&gt;
&lt;p&gt;I also started to work on the NIST database by fixing a parsers developed last year. Though I can plot NIST spectra for some wavelength, there still are issues particularly about the FWHM to deal with.&lt;/p&gt;
&lt;img alt="" height="1" src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=e955d61c1591" width="1"&gt;</description><category>radis</category><guid>http://openastronomy.org/Universe_OA/posts/2023/08/20230811_1723_menasrac/</guid><pubDate>Fri, 11 Aug 2023 16:23:24 GMT</pubDate></item><item><title>Adapting Kurucz to SpectrumFactory and what is next ?</title><link>http://openastronomy.org/Universe_OA/posts/2023/07/20230729_2343_menasrac/</link><dc:creator>Racim MENASRIA</dc:creator><description>&lt;h4&gt;&lt;strong&gt;Adapting Kurucz to SpectrumFactory and what is next ?&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;After my first pull request I received some feedback.&lt;br&gt;Optional and major changes were requested. The most important changes were that my code should &lt;strong&gt;better integrate the existing Radis code&lt;/strong&gt;. Indeed, though I added a new database with Kurucz, its API remained distinct which is something which will make Radis progress toward a common API.&lt;/p&gt;
&lt;p&gt;Another key remark was that my code didn’t take into account the &lt;strong&gt;Broadening effects&lt;/strong&gt; that modify the lineshapes.&lt;br&gt;This is why I had a Team meeeting with my mentors to discuss the physics behind the code. It helped me a lot to understand what was expected.&lt;/p&gt;
&lt;p&gt;After this I worked on adding broadening and merging the new AdB Kurucz with SpectrumFactory. In order to do so, I worked on an example which allows to plot a spectrum using the Kurucz atomic data and &lt;strong&gt;SpectrumFactory.&lt;/strong&gt; My first attempt was to use one of the existing Radis formats for databanks named &lt;strong&gt;hdf5-radisdb&lt;/strong&gt; since I worked with hdf5 files in my Class.&lt;br&gt;This attempt happened to be too difficult because the formats were made for molecules and too many columns of my dataframe were different from the expected columns.&lt;br&gt;This is why I eventually decided to add &lt;strong&gt;a new format named “kurucz” &lt;/strong&gt;to the load_databank method which allows to load the kurucz data with the proper form.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;p&gt;Then, I worked on the &lt;strong&gt;eq_spectrum&lt;/strong&gt; method to adjust it to this newformat.&lt;br&gt;I added some methods and adapted methods from Exojax to handle linestrength computation, broadening,convolution,pressure layers and create a Spectrum Object. It took me a lot of efforts and I modified many files as Broadening.py, Base.by,Factory.py or loader.py.&lt;br&gt;However, the results of the Spectrum I obtained were not convincing and some parameters and units didn’t fit properly.&lt;/p&gt;
&lt;p&gt;Moreover, by the time I wrote this spectrocopy code, I fell behind in my project, that’s why we organized a long meeting with one of my supervisors in order to take stock, we adjusted the objectives of the project.&lt;/p&gt;
&lt;h4&gt;We gave up the last one about adding the CIA database and agreed on the following timeline :&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;finishing with SpectrumFactory for Kurucz ASAP&lt;/li&gt;&lt;li&gt;Moving to NIST&lt;/li&gt;&lt;li&gt;Then working on the DatabaseManager Class architecture and adapting to AdB and MdB manager subclasses&lt;/li&gt;&lt;li&gt;Moving to the TheoreTS ( it will require to reach people in Reims to fix the db that I still cannot access).&lt;/li&gt;&lt;li&gt;Working on developing an example during the last week to show what applications the atomic spectra physics brings.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We also noticed that I had written my Spectrum Factory example from the beginning rather than using the existing radis methods which is why I lost time and it was unaccurate. However, the meeting brought me the right guidelines and working on this code allowed me to getting a better understanding of the architecture and adapting the example to the existing structure of the code should be easier now. We also discussed about a few existing codes which could be a could starting point for adding NIST to Kurucz.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;The next weeeks will take me a lot of time and effort to complete the objectives but in the end, I am happy that we had this meeting because it unblocked me when I was kinda stuck with Kurucz for a while.&lt;/p&gt;
&lt;img alt="" height="1" src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=d3453292daf1" width="1"&gt;</description><category>radis</category><guid>http://openastronomy.org/Universe_OA/posts/2023/07/20230729_2343_menasrac/</guid><pubDate>Sat, 29 Jul 2023 22:43:53 GMT</pubDate></item><item><title>Setting Up for the Kurucz PR and transitioning to the TheoReTS</title><link>http://openastronomy.org/Universe_OA/posts/2023/07/20230702_1407_menasrac/</link><dc:creator>Racim MENASRIA</dc:creator><description>&lt;p&gt;This week was not the most enjoyable phase of the project so far, as I had to exert considerable effort to fix failing tests before opening a pull request.&lt;/p&gt;
&lt;p&gt;Once I ensured that the initial tests passed, I wrote my own tests to confirm that the new AdB Kurucz class didn’t interfere with any part of the existing code. At this point, I encountered a primary issue. I hadn’t noticed that one of the methods I had adapted from ExoJAX was still reading a file which necessitated an ExoJAX package dependency. This caused the build to fail on GitHub due to one of the tests in my kurucz_test.py file failing.&lt;/p&gt;
&lt;p&gt;Since there’s a conflict related to the JAX installation on Windows, I couldn’t add it to the requirements file. Doing so would create a conflict for every Windows user installing Radis. Consequently, I had to write a program to extract the data from this package and store a copy of it in a local file called pfdat.txt. This enabled the problematic function to read from the local copy instead of the ExoJAX file. This solution successfully rectified the problem, and now my PR passes the tests and is awaiting review before merging.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;p&gt;The next step is to transition to the TheoReTS as planned. According to the TheoReTS website, it is an information system for theoretical spectra based on variational predictions from molecular potential energy and dipole moment surfaces. It is jointly developed by the PMT team of GSMA (Reims), Tomsk University, and IAO Acad Sci. Russia. As a result, it provides two access points, one French and the other Russian. However, I noticed that the access to the French website (&lt;a href="http://theorets.univ-reims.fr/"&gt;http://theorets.univ-reims.fr/&lt;/a&gt;) is currently unavailable, preventing me from visualizing the data. This is an issue I should discuss with my mentors.&lt;/p&gt;
&lt;img alt="" height="1" src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=d9643c0269aa" width="1"&gt;</description><category>radis</category><guid>http://openastronomy.org/Universe_OA/posts/2023/07/20230702_1407_menasrac/</guid><pubDate>Sun, 02 Jul 2023 13:07:42 GMT</pubDate></item><item><title>Implementation of the Kurucz database to Radis</title><link>http://openastronomy.org/Universe_OA/posts/2023/06/20230617_2033_menasrac/</link><dc:creator>Racim MENASRIA</dc:creator><description>&lt;p&gt;As planed in my last article, I started my project by adding a first database to Radis : Kurucz.&lt;/p&gt;
&lt;p&gt;I based my work on a existing class developed in Exojax. I reviewed the associated methods that allowed to download the data from the database, store it in numpy arrays and extract the key information from it for further calculation.&lt;/p&gt;
&lt;p&gt;By running a few examples on Exojax, I got familiar with the structure and nature of the data and key functions.&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;p&gt;However, I noticed a problem in the install command of Radis’s sister code Exojax while running theses examples. After further investigation with my mentors and the Exojax team, it appeared to be a jax problem so we couldn’t fix it for the moment.&lt;br&gt;Since I could only make them work on a wsl environment, I couldn’t afford to import jax libraries used in the AdbKurucz database implemented to Exojax. This is the reason why I had to adapt the structure of the data and methods and stick to Pandas dataframes and numpy arrays.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;First try : using a DatabaseManager structure&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;As a explained it in the previous article, Radis has developed a special Class the handle the database processes. Since Kurucz is an atomic Database, I tried to implement it by making it inherit from the DatabaseManager class and setting the molecule parameter to “None”. Unfortunately, it led to many exceptions in the methods that I gave up on this idea.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Second try : using Exojax methods without jax imports&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;This approach provided very nice results because the major part of the methods were already efficient. &lt;br&gt;Nevertheless I had some errors because of the data wasn’t loaded properly or syntax errors had broken a few parts of the code.&lt;/p&gt;
&lt;p&gt;I finally managed to load, store and use the data from Kurucz.&lt;/p&gt;
&lt;p&gt;Then I added an example to show how this new database can be used.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oJXYNuWaqdZFCpuhYTNSjw.png"&gt;&lt;/figure&gt;&lt;p&gt;This is the first spectrum that I obtained from the Kurucz database for Fe.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;A bit more explanations:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The population of the lower energy level of a given transition is the number of atoms that are in that energy state at any given time. So if you have a large population in a certain energy state, you have a lot of atoms that are able to make the transition and therefore emit a photon. Einstein’s coefficient A for a particular transition is a measure of the probability of that transition occurring. So if A is large, then each atom has a high chance of making the transition and emitting a photon. Thus, the intensity of the spectral line (i.e. the number of photons emitted per unit time) is proportional to both the population of the lower energy level (the number of atoms capable of making the transition) and to A (the probability that each atom actually makes the transition). So the intensity can be approximately represented as A * population.&lt;/p&gt;
&lt;p&gt;The users can chose the temperature and the function then interpolates the values from the database and plots the spectrum.&lt;/p&gt;
&lt;p&gt;In order to generalize this to all the atoms and ions of the database, I had to adjust the function load_pf_Barklem2016() from Exojax and fix an error in the way the partition functions were extracted.&lt;/p&gt;
&lt;p&gt;Now I can load the data and use it properly. For Kurucz’s data, each file corresponds to a single species of atom only. For example, “gf2600.all” is dedicated to absorption lines of “neutral iron atoms”. The “26” is the atomic number of iron, followed by a “00” indicating zero ionization (=neutral; Fe I). For example, if you want to use spectral lines of singly-ionized sodium (Na II or Na+), you should download “gf1101.all”.&lt;/p&gt;
&lt;p&gt;Here is another example for Ca.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1024/1*q_748Zt_K4rqW5fWtFAdTQ.png"&gt;&lt;/figure&gt;&lt;h4&gt;&lt;strong&gt;What is next ?&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;I will end up this week by adding a few tests to ensure my code doesn’t break any part of the Radis architecture and may go for a PR in the next days.&lt;/p&gt;
&lt;p&gt;Then the next step for Week 4 will be to implement the TheoReTS database to Radis .&lt;/p&gt;
&lt;img alt="" height="1" src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=27c2724fde74" width="1"&gt;</description><category>radis</category><guid>http://openastronomy.org/Universe_OA/posts/2023/06/20230617_2033_menasrac/</guid><pubDate>Sat, 17 Jun 2023 19:33:30 GMT</pubDate></item><item><title>GSOC Week 1 : A global overview of the RADIS API.</title><link>http://openastronomy.org/Universe_OA/posts/2023/06/20230604_2227_menasrac/</link><dc:creator>Racim MENASRIA</dc:creator><description>&lt;h4&gt;GSOC Week 1 : A global overview of the RADIS API.&lt;/h4&gt;&lt;p&gt;Since the point of my project is to implement new databases in the RADIS API and to reform it in other to make it common and stand alone, it seems important to understand how this API works.&lt;/p&gt;
&lt;p&gt;Thus, I have started my 12 weeks projects by reading carefully the API documentation available at &lt;a href="https://radis.readthedocs.io/en/latest/source/radis.io.dbmanager.html"&gt;https://radis.readthedocs.io/en/latest/source/radis.io.dbmanager.html&lt;/a&gt;. I will detail in this article what I consider the key points to understand how Radis works globally and aim to answer the following question : Whats are the steps to proceed in order to include a new database as Kurucz to RADIS ?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This page is a description of the different modules available in the RADIS library except the api one which will be discussed later.&lt;/strong&gt;&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/1017/1*UPlH0eBh97WoVpiEn_C7rQ.png"&gt;&lt;/figure&gt;&lt;p&gt;In particular, the radis.io package provided functionality for file management, downloading and analysis of different spectroscopic databases.&lt;/p&gt;
&lt;p&gt;To understand in detail how the RADIS API works and integrate a new database like Kurucz, here are the most important radis.io package sub-modules to explore :&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;dbmanager&lt;/strong&gt; : This submodule used to contain the DatabaseManager class, which is the heart of database management in RADIS before it was moved to the api module. Understanding how this class is used to save, download, manipulate and interact with existing databases is essential. I will also need to understand how to add a new database by implementing the appropriate methods.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;geisa, hitran or exomol : &lt;/strong&gt;I have to study how GEISA, HITRAN or Exomol files are downloaded, saved and processed. Understanding how this databases are integrated will give me an idea of the structure and workflow needed to integrate a new database.&lt;/p&gt;
&lt;h4&gt;The DatabaseManager class&lt;/h4&gt;&lt;p&gt;The DatabaseManager class aims to handle and manage files from various databases. It provides a generic framework for managing and caching files from different sources or databases.&lt;/p&gt;
&lt;pre&gt;class DatabaseManager(object):&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;add_column(df, key, value)&lt;/strong&gt;: This method allows to create a column with a key and a value specified in a DataFrame or a dictionary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;check_deprecated_files(local_files, auto_remove=True)&lt;/strong&gt;: This method checks file metadata and removes deprecated ones. If auto_remove is set to True, deprecated files will be automatically removed. Otherwise, an error will be thrown.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;clean_download_files()&lt;/strong&gt;: This method cleans downloaded and unzipped files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;download_and_parse(urlnames, local_files)&lt;/strong&gt;: This method downloads and parses files from the specified URLs and saves them locally.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;fetch_filenames()&lt;/strong&gt;: This method fetches the names of all files from the database, even if they haven’t been downloaded yet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;fetch_urlnames()&lt;/strong&gt;: This method must be overridden in the DatabaseManager subclass. It should return a list of URLs corresponding to database files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;get_columns(local_file)&lt;/strong&gt;: This method retrieves all the columns available in a database file using the get_columns function of the DataFileManager class.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;load(local_files, columns=None, lower_bound=[], upper_bound=[], within=[], output=’pandas’):&lt;/strong&gt; This method loads data from database files. You can specify which columns to load, lower and upper bounds for values in certain columns, and constraints for certain columns. You can also specify the output format, such as ‘pandas’, ‘vaex’ or ‘jax’.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;plot(local_files, isotope, wavenum_min, wavenum_max):&lt;/strong&gt; This method is a convenience function for plotting the linestrengths of the database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;register(dict_entries):&lt;/strong&gt; This method registers dictionary entries for a specified database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;remove_local_files(local_files)&lt;/strong&gt;: This method removes the specified local files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;rename_columns(df, rename_dict):&lt;/strong&gt; This method renames the columns of a DataFrame using a dictionary of correspondence between the old column names and the new names.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;register_database(databank_name, dict_entries, verbose): &lt;/strong&gt;This method adds registered databases to the RADIS configuration file.&lt;/p&gt;
&lt;h4&gt;The radis.io.geisa module review : to get some ideas ?&lt;/h4&gt;&lt;p&gt;The GEISADatabaseManager class is a subclass of DatabaseManager which is specifically designed to manage GEISA databases. It adds specific functionalities to the management of GEISA files and their integration into the RADIS API. It gives us an insight of what the implemenation of other databases as Kurucz should look like. However, every database has its own specificities that is why the methods may differ on some aspects though they are built on a same basis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;fetch_urlnames(): &lt;/strong&gt;This method must be implemented to return a list of URLs corresponding to GEISA files in your database. These URLs will be used to download files from the GEISA website.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;parse_to_local_file():&lt;/strong&gt; This method is used to unpack GEISA files and save them locally. It also adds metadata to files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;register():&lt;/strong&gt; This method registers the GEISA database in the RADIS configuration file. It ensures that the RADIS API recognizes and can access the database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;fetch_geisa():&lt;/strong&gt; This GEISA specific method fetches GEISA files from the GEISA website, unpacks them and creates an HDF5 file containing all row data. It returns a Pandas DataFrame containing all rows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;columns_GEISA:&lt;/strong&gt; It is a dictionary that defines the parsing order of columns in the GEISA2020 format. It specifies column names, data types, descriptions, and units.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;engine:&lt;/strong&gt; This is an optional parameter that allows to specify the memory mapping library to use for the GEISA database. By default, it uses the ‘default’ value specified in the RADIS configuration file.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;verbose, chunksize, parallel:&lt;/strong&gt; These are optional parameters to control the verbosity level of informational messages, the size of chunks for loading data and the use of parallel loading.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The fetch_geisa() &lt;/strong&gt;method is an example of using the GEISADatabaseManager class to retrieve GEISA data for a specific molecule. This method downloads GEISA files from the GEISA website, unpacks them and saves them locally. It returns a Pandas DataFrame containing all rows from the GEISA database for the specified molecule.&lt;/p&gt;
&lt;p&gt;Before exploring the Kurucz database structure more in details, let is discuss the other modules of the RADIS API.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;The db module :&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Definition of molecules:&lt;/strong&gt; The db module allows to define the molecules used in the spectroscopic calculations. You can specify isotopes, molecular weights, chemical symbols, and other relevant molecular properties.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Spectroscopic constants: &lt;/strong&gt;The db module stores the spectroscopic constants associated with each molecule, such as electronic transitions, energy levels, frequencies, absorption intensities, cross sections, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data Access&lt;/strong&gt;: The db module provides methods and data structures to easily access information about molecules and spectroscopic constants.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Database extensions:&lt;/strong&gt; The db module allows extending the functionalities of the database by adding new molecules, isotopes or spectroscopic constants. Here it is possible to add new data or integrate external databases to enrich the capabilities of RADIS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interoperability:&lt;/strong&gt; The db module facilitates interoperability with other libraries and spectroscopic data formats. It allows to import and export spectroscopic data in different formats, such as HITRAN, HITEMP, GEISA, Kurucz, etc.&lt;/p&gt;
&lt;h4&gt;What about Exojax ?&lt;/h4&gt;&lt;p&gt;Another open-source code, called EXOJAX, exchanged portions of code with RADIS until some parts of both codes became very similar. Currently, a database API is written in the RADIS code.&lt;/p&gt;
&lt;p&gt;Understanding how Radis and Exojax somehow partially merged will be useful to understand how to implement a new database.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;May 2022 &lt;/strong&gt;: an example of an Exojax-like syntax was added in the exomol.py file. This example introduces a new class called mdbExomol, which holds Jax arrays as attributes. This class is based on DataFrame loading and is designed to be a drop-in replacement for Exojax computations.&lt;/p&gt;
&lt;pre&gt;mport pathlib&lt;br&gt;&lt;br&gt;import numpy as np&lt;br&gt;&lt;br&gt;from radis.api.exomolapi import (&lt;br&gt;    MdbExomol,&lt;br&gt;    get_exomol_database_list,&lt;br&gt;    get_exomol_full_isotope_name,&lt;br&gt;)&lt;br&gt;from radis.db.classes import get_molecule_identifier&lt;br&gt;&lt;br&gt;&lt;br&gt;def fetch_exomol(&lt;br&gt;    molecule,&lt;br&gt;    database=None,&lt;br&gt;    local_databases=None,&lt;br&gt;    databank_name="EXOMOL-{molecule}",&lt;br&gt;    isotope="1",&lt;br&gt;    load_wavenum_min=None,&lt;br&gt;    load_wavenum_max=None,&lt;br&gt;    columns=None,&lt;br&gt;    cache=True,&lt;br&gt;    verbose=True,&lt;br&gt;    clean_cache_files=True,&lt;br&gt;    return_local_path=False,&lt;br&gt;    return_partition_function=False,&lt;br&gt;    engine="default",&lt;br&gt;    output="pandas",&lt;br&gt;    skip_optional_data=True,&lt;br&gt;):&lt;/pre&gt;&lt;p&gt;Here is a description of each function parameter:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;molecule&lt;/strong&gt;: The name of the molecule for which we want to retrieve data.&lt;br&gt;database: The name of the specific ExoMol database to use. If the value is None or “default”, the recommended database will be used.&lt;br&gt;local_databases: The path to the local directory where the ExoMol database files will be stored.&lt;br&gt;&lt;strong&gt;databank_name:&lt;/strong&gt; The name to give to the ExoMol database.&lt;br&gt;isotope: The number of the specific isotope of the molecule for which you want to retrieve data.&lt;br&gt;&lt;strong&gt;load_wavenum_min and load_wavenum_max:&lt;/strong&gt; The minimum and maximum wavenumbers to load.&lt;br&gt;&lt;strong&gt;columns: &lt;/strong&gt;A list of specific columns to load from ExoMol files.&lt;br&gt;&lt;strong&gt;cache:&lt;/strong&gt; A boolean indicating whether files should be cached for later use.&lt;br&gt;&lt;strong&gt;verbose:&lt;/strong&gt; A boolean indicating whether informational messages should be displayed during the process.&lt;br&gt;&lt;strong&gt;clean_cache_files:&lt;/strong&gt; A boolean indicating whether cached files should be removed after use.&lt;br&gt;&lt;strong&gt;return_local_path and return_partition_function:&lt;/strong&gt; Booleans indicate whether local path to files and partition function should be returned in addition to data.&lt;/p&gt;
&lt;p&gt;The function starts by checking the settings and determining which ExoMol database to use. Next, it creates an MdbExomol object to manage the ExoMol database, downloading files as needed. The local files are then loaded into a DataFrame, with specific columns if needed. RADIS-specific manipulations are performed on the DataFrame, such as renaming columns and adding additional data. Eventually the DataFrame is returned, possibly with other information if selected.&lt;/p&gt;
&lt;p&gt;Then &lt;a href="https://medium.com/u/1169335fca8"&gt;Erwan Pannier&lt;/a&gt; added an Example of an Exojax-like syntax, creating a ``mdbExoMol` class holding jax arrays as Attributes (based on DataFrame loading), so it can be used as a drop-in replacement&lt;/p&gt;
&lt;p&gt;The example also shows how to : Compute an Exomol CH4 spectrum with Radis Load Exomol CH4 Jax arrays ready for an Exojax computation, by downloading the files to the .database local folder Load Exomol CH4 Jax arrays ready for an Exojax computation, by loading the files from the Radis’s database of (1) For 2. and 3., a local_databases= parameter allows to easily switch in between any local folder (to save on download &amp;amp; caching times if comparing the two codes)&lt;/p&gt;
&lt;p&gt;Here is the code ( available on &lt;a href="https://github.com/radis/radis/blob/e317c994451d3afa02b1fa63d90ae0eb546f36ed/radis/io/exomol.py#L925"&gt;radis/exomol.py at e317c994451d3afa02b1fa63d90ae0eb546f36ed · radis/radis (github.com)&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt;   #%% RADIS-like Example&lt;br&gt;    # uses fetch_exomol() internally&lt;br&gt;&lt;br&gt;    from radis import calc_spectrum&lt;br&gt;&lt;br&gt;    s = calc_spectrum(&lt;br&gt;        wavelength_min=1.630e4,&lt;br&gt;        wavelength_max=1.6305e4,&lt;br&gt;        molecule="CH4",&lt;br&gt;        isotope="1",&lt;br&gt;        pressure=1.01325,  # bar&lt;br&gt;        Tgas=1000,  # K&lt;br&gt;        mole_fraction=0.1,&lt;br&gt;        path_length=1,  # cm&lt;br&gt;        # broadening_method="fft",  # @ dev: Doesn't work with 'voigt'&lt;br&gt;        databank=(&lt;br&gt;            "exomol",&lt;br&gt;            "YT10to10",&lt;br&gt;        ),  # Simply use 'exomol' for the recommended database&lt;br&gt;    )&lt;br&gt;    # s.apply_slit(1, "cm-1")  # simulate an experimental slit&lt;br&gt;    s.plot("xsection")&lt;br&gt;&lt;br&gt;    # %% Exojax like Example&lt;br&gt;&lt;br&gt;    class mdbExoMol:&lt;br&gt;&lt;br&gt;        # hardcode attribute names, to prevent typos and the declaration of unwanted parameters&lt;br&gt;        __slots__ = [&lt;br&gt;            "Sij0",&lt;br&gt;            "logsij0",&lt;br&gt;            "nu_lines",&lt;br&gt;            "A",&lt;br&gt;            "elower",&lt;br&gt;            "eupper",&lt;br&gt;            "gupper",&lt;br&gt;            "jlower",&lt;br&gt;            "jupper",&lt;br&gt;        ]&lt;br&gt;&lt;br&gt;        def __init__(&lt;br&gt;            self,&lt;br&gt;            molecule,&lt;br&gt;            path,&lt;br&gt;            nurange=[-np.inf, np.inf],&lt;br&gt;            crit=-np.inf,&lt;br&gt;            local_databases="~/exojax",&lt;br&gt;        ):&lt;br&gt;            """&lt;br&gt;            Parameters&lt;br&gt;            ----------&lt;br&gt;            molecule: molecule name&lt;br&gt;            path : local path, mirror of ExoMol path&lt;br&gt;            nurange : TYPE, optional&lt;br&gt;                DESCRIPTION. The default is [-np.inf, np.inf].&lt;br&gt;            crit : TYPE, optional&lt;br&gt;                DESCRIPTION. The default is -np.inf.&lt;br&gt;&lt;br&gt;            Returns&lt;br&gt;            -------&lt;br&gt;            DataFrame&lt;br&gt;&lt;br&gt;            Examples&lt;br&gt;            --------&lt;br&gt;            ::&lt;br&gt;&lt;br&gt;                mdbCH4 = mdbExoMol("CH4", '.database/CH4/12C-1H4/YT10to10/', nus, crit=1.e-30)&lt;br&gt;                print(len(mdbCH4.nu_lines), "lines")&lt;br&gt;                mdbCH4.elower&lt;br&gt;&lt;br&gt;            Available columns::&lt;br&gt;&lt;br&gt;                [&lt;br&gt;                    "Sij0",&lt;br&gt;                    "logsij0",&lt;br&gt;                    "nu_lines",&lt;br&gt;                    "A",&lt;br&gt;                    "elower",&lt;br&gt;                    "eupper",&lt;br&gt;                    "gupper",&lt;br&gt;                    "jlower",&lt;br&gt;                    "jupper",&lt;br&gt;                ]&lt;br&gt;&lt;br&gt;            """&lt;br&gt;&lt;br&gt;            wavenum_min, wavenum_max = np.min(nurange), np.max(nurange)&lt;br&gt;            if wavenum_min == -np.inf:&lt;br&gt;                wavenum_min = None&lt;br&gt;            if wavenum_max == np.inf:&lt;br&gt;                wavenum_max = None&lt;br&gt;&lt;br&gt;            # Set-up database, download files and set-up cache files if needed&lt;br&gt;            mdb = MdbExomol(&lt;br&gt;                path,&lt;br&gt;                molecule=molecule,&lt;br&gt;                local_databases=local_databases,&lt;br&gt;                nurange=[wavenum_min, wavenum_max],&lt;br&gt;            )&lt;br&gt;&lt;br&gt;            # Get cache files to load :&lt;br&gt;            mgr = mdb.get_dframe_manager()&lt;br&gt;            local_files = [mgr.cache_file(f) for f in mdb.trans_file]&lt;br&gt;&lt;br&gt;            # Load them:&lt;br&gt;            jdict = mdb.load(&lt;br&gt;                local_files,&lt;br&gt;                columns=[k for k in self.__slots__ if k not in ["logsij0"]],&lt;br&gt;                lower_bound=([("nu_lines", wavenum_min)] if wavenum_min else [])&lt;br&gt;                + ([("Sij0", mdb.crit)] if not np.isneginf(mdb.crit) else []),&lt;br&gt;                upper_bound=([("nu_lines", wavenum_max)] if wavenum_max else []),&lt;br&gt;                output="jax",&lt;br&gt;            )&lt;br&gt;&lt;br&gt;            # set attributes, accessible as e.g:  mdb.nu_lines&lt;br&gt;            for k in jdict.keys():&lt;br&gt;                setattr(self, k, jdict[k])&lt;br&gt;&lt;br&gt;    nus = np.linspace(1e7 / 1.630e4, 1e7 / 1.6305e4)&lt;br&gt;&lt;br&gt;    # Download new ExoMol repo (in ~/exomol)&lt;br&gt;    mdbCH4 = mdbExoMol(&lt;br&gt;        "CH4",&lt;br&gt;        ".database/CH4/12C-1H4/YT10to10/",&lt;br&gt;        nus,&lt;br&gt;        crit=1.0e-30,&lt;br&gt;        local_databases=".",  # use local folder&lt;br&gt;    )&lt;br&gt;&lt;br&gt;    print(len(mdbCH4.nu_lines), "lines")&lt;br&gt;    mdbCH4.elower&lt;br&gt;&lt;br&gt;    # Or use RADIS's folder  (# by default ~/.radisdb/exomol)&lt;br&gt;    import radis&lt;br&gt;&lt;br&gt;    mdbCH4_2 = mdbExoMol(&lt;br&gt;        "CH4",&lt;br&gt;        "CH4/12C-1H4/YT10to10/",&lt;br&gt;        nus,&lt;br&gt;        crit=1.0e-30,&lt;br&gt;        local_databases=pathlib.Path(radis.config["DEFAULT_DOWNLOAD_PATH"]) / "exomol",&lt;br&gt;    )&lt;br&gt;    # ... ready to run Jax calculations&lt;/pre&gt;&lt;p&gt;The example added in the exomol.py file of RADIS demonstrates how to create an “mdbExoMol” class similar to Exojax, which uses jax arrays as attributes. This class allows loading ExoMol data as jax arrays, making them compatible with Exojax.&lt;/p&gt;
&lt;p&gt;The example illustrates how to calculate a CH4 spectrum using RADIS by utilizing the “mdbExoMol” class. It also shows how to load the jax arrays ready for use in an Exojax computation by downloading the files into a local “.database” folder. Additionally, the example demonstrates how to load the jax arrays from the RADIS database, enabling easy switching between different local databases by specifying the “local_databases” parameter.&lt;/p&gt;
&lt;h4&gt;Toward a common API ?&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Preliminary work in Radis #465&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This preliminary work was done to prepare for a meeting between RADIS and ExoJax to discuss the implementation of a common API for database management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The rationale behind this work is to maintain three layers of agnosticism to simplify the user experience:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Users should not have to worry about the specific format of the input database,&lt;/strong&gt; such as HITRAN 2012, HITRAN 2020, HITEMP, GEISA, ExoMol, Kuruz, NIST, etc. This allows for easy integration of new libraries and ensures that all codes can benefit from all available libraries.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Users should not have to be concerned about the format in which the data is stored on disk&lt;/strong&gt;, whether it’s Vaex’s HDF5, Pandas’s HDF5, Feather, or other formats. This flexibility enables the switch to more performant libraries when they become available, such as PyArrow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Users should have the freedom to choose the output format used in calculations&lt;/strong&gt;, whether it’s Pandas’s DataFrame, Jax arrays, Vaex DataFrame, or others. This allows for data retrieval in the desired format for each code, such as Jax for ExoJax, Pandas for the current RADIS implementation, or Vaex for future fully-out-of-core RADIS for extreme databases.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Radis state in May 2022&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;ExoJax &lt;/strong&gt;has MdbExomol or MdbHIt . They are similar but don’t inherit from a common base ;&lt;br&gt;&lt;strong&gt;RADIS 0.12 has a DatabaseManager&lt;/strong&gt; to handle HITEMP 2020 / HITRAN 2020; the ExoMol support is done with a MdBMol taken from Exojax with no link with the DatabaseManager.&lt;br&gt;RADIS implemented a &lt;strong&gt;DataFileManager&lt;/strong&gt; &lt;strong&gt;class&lt;/strong&gt; to handle (Vaex’s HDF5; Pandas’s HDF5, Feather) ; DatabaseManager calls DataFileManager internally &lt;br&gt;Radis Exomol api update #464 added &lt;strong&gt;3 output : ’jax/vaex/pandas’&lt;/strong&gt; to RADIS’s DatabaseManager&lt;/p&gt;
&lt;p&gt;Here Radis then suggest a code a demonstration :&lt;/p&gt;
&lt;pre&gt;# Test ExoMol&lt;br&gt;&lt;br&gt;import radis&lt;br&gt;radis.config["MEMORY_MAPPING_ENGINE"] = "vaex" # 👉👉👉  choose  "vaex", "pytables", "feather"&lt;br&gt;&lt;br&gt;from radis.io.exomol import fetch_exomol&lt;br&gt;&lt;br&gt;df = fetch_exomol("SiO", database="EBJT", isotope="1", load_wavenum_max=5000, &lt;br&gt;        output="pandas" # 👉👉👉 choose : "pandas", "vaex", "jax"&lt;br&gt;        )&lt;br&gt;print(df)&lt;br&gt;&lt;br&gt;&lt;/pre&gt;&lt;p&gt;This code allows you to fetch ExoMol data for the SiO molecule from the specified database, control the output format, and print the resulting DataFrame.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;MdbExomol class&lt;/strong&gt; is a molecular database class specifically designed for ExoMol, which is a database of molecular line lists for exoplanet and other hot atmospheres. It is a subclass of the DatabaseManager class.&lt;/p&gt;
&lt;p&gt;The MdbExomol class has the following parameters:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;path&lt;/strong&gt;: The path for the ExoMol data directory or tag.&lt;br&gt;nurange: A wavenumber range list (in cm-1) or a wavenumber array.&lt;br&gt;margin: A margin for the wavenumber range (in cm-1).&lt;br&gt;&lt;strong&gt;crit:&lt;/strong&gt; The line strength lower limit for extraction.&lt;br&gt;&lt;strong&gt;bkgdatm&lt;/strong&gt;: The background atmosphere for broadening, e.g., H2, He.&lt;br&gt;broadf: If False, the default broadening parameters in the .def file are used.&lt;br&gt;Additionally, there are other parameters such as engine and skip_optional_data that control the memory mapping engine and the loading of optional data from the ExoMol definition file, respectively.&lt;/p&gt;
&lt;p&gt;The MdbExomol class provides methods to load and manage the ExoMol data files. It converts the trans/states files to feather or HDF5 format for efficient loading. The loaded data is stored in a DataFrame with columns such as nu_lines, Sij0, A, elower, gpp, jlower, and more. These columns contain information about line centers, line strengths, Einstein A coefficients, lower state energy, statistical weight, J_lower, and other relevant parameters.&lt;/p&gt;
&lt;p&gt;The class also provides examples of how to initialize the database, download the necessary files, and load the data. It references the original publications on ExoMol for more information.&lt;/p&gt;
&lt;h5&gt;Discussion between Radis and Exojax&lt;/h5&gt;&lt;p&gt;The question of hosting the common API was addressed for the first time in discussion&lt;strong&gt; #257&lt;/strong&gt;. It is suggested to create a new directory or module within Radis for the common API. However, it is noted that this may make development difficult if specific Radis features need to be integrated into the common API. A suggestion is made to create a separate module, such as “radis.api”, which would house the common API.&lt;/p&gt;
&lt;p&gt;A proposed structure was discussed, where the DatabaseManager class is considered the core common API. Subclasses, such as HitranManager and ExomolManager, inherited from DatabaseManager to provide the specific functionalities for the Hitran and Exomol databases, respectively.&lt;/p&gt;
&lt;p&gt;A suggestion was made to create a MdbHitran class (inheriting from HitranManager) and a MdbExomol class (inheriting from ExomolManager) for the ExoJAX API. These classes would have their own ExoJAX-specific methods, allowing ExoJAX to integrate with the common API.&lt;/p&gt;
&lt;p&gt;Radis and Exojax agreed that separating the functionalities into separate folders is a good approach to avoid conflicts between Radis-specific and ExoJAX-specific features. Additionally, they suggested to add tests to ensure that ExoJAX requirements were tested within Radis without causing any issues.&lt;/p&gt;
&lt;p&gt;It starts from the “radis.api” folder for the common API, which would be included within Radis. This approach would allow for the development of the common API while maintaining a close connection with Radis. Furthermore, the possibility of creating a new directory or module for an independent API in the future is considered, to allow the common API to become independent if needed.&lt;/p&gt;
&lt;p&gt;In summary, the conversation revolves around the hosting and structure of the common API between Radis and ExoJAX. It is decided to create a separate module, “radis.api”, for the common API while keeping the possibility of independent development in the future. Specific classes are proposed for ExoJAX, enabling the integration of ExoJAX into the common API. Measures are taken to separate Radis-specific and ExoJAX-specific functionalities and to test ExoJAX requirements within Radis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;After this discussion, a series of measures was implemented to Radis in PR # 480&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The common functions shared between Exojax and Radis were moved to the &lt;strong&gt;“radis/api”&lt;/strong&gt; directory, allowing for better organization and separation of concerns.&lt;br&gt;Parts of Hitran, Hitemp, CDSD, and GEISA &lt;strong&gt;that were common to both Exojax and Radis were also moved to the “radis/api”&lt;/strong&gt; directory.&lt;br&gt;The Exomol files were combined and moved to the “radis/api” directory, and tests were fixed accordingly.&lt;br&gt;The io.tools module was moved to the “radis/api/tools” directory for better organization.&lt;br&gt;Links in the documentation and docstrings were renamed to reflect the changes in the code structure.&lt;br&gt;Some missing files were added, isort errors on CI were fixed, and unclosed HDF5 files were addressed.&lt;br&gt;The Exomol documentation was updated, and error messages were improved.&lt;br&gt;The set_broadenings function was made compatible with both vaex and pandas DataFrames.&lt;br&gt;Modifications were made to the set_broadening function, including assuming a dictionary as input for unknown DataFrames and redefining the function to store values in a DataFrame.&lt;br&gt;The MdbExomol instance now includes self.molmass.&lt;br&gt;The codebase was merged with the upstream “add/common-api” branch.&lt;br&gt;Some abspath problems were fixed, and error messages were improved.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In November 2022, the version 0.14 was released and the common API with Exojax was added to Radis.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Review of the exomolapi.py code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This code is an API for accessing and using data from the ExoMol project. It includes a main class MdbExomol that allows downloading and accessing ExoMol files, as well as performing spectral calculations. The MdbExomol class provides methods for downloading files, creating PartFuncExoMol objects, and loading specific line data.&lt;/p&gt;
&lt;p&gt;The download function allows downloading ExoMol files from a specified URL and saving them locally. The to_partition_function_tabulator function generates a PartFuncExoMol object from the ExoMol-specific partition function data.&lt;/p&gt;
&lt;p&gt;The if __name__ == “__main__” section contains examples of using the MdbExomol class and other features of the API, including spectrum calculations using the RADIS library, and downloading and accessing ExoMol line data using the fetch_exomol function.&lt;/p&gt;
&lt;p&gt;Thus, the ExoMol API provides tools for downloading, manipulating, and utilizing spectroscopic data from the ExoMol project, including transition files, partition functions, and calculated spectra.&lt;/p&gt;
&lt;h4&gt;Conclusion : How should I proceed to add to Radis a new database as Kurucz ?&lt;/h4&gt;&lt;p&gt;Regarding implementing Kurucz, the structure of the exomolapi.py code can serve as a model for building a similar API for Kurucz data. I may create a class similar to MdbExomol that handles downloading Kurucz files, accessing the relevant data (such as atomic and molecular line data, partition functions, etc.), and provides methods for spectral calculations and other functionalities specific to Kurucz. I will have to adapt and modify the existing code to suit the data format and organization of Kurucz data.&lt;br&gt;In order to do so, I will review the structure of the Kurucz database and make a quick report in a next post before starting the implementation.&lt;/p&gt;
&lt;img alt="" height="1" src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=fc58bc4e9979" width="1"&gt;</description><category>radis</category><guid>http://openastronomy.org/Universe_OA/posts/2023/06/20230604_2227_menasrac/</guid><pubDate>Sun, 04 Jun 2023 21:27:53 GMT</pubDate></item><item><title>Blog GSoC project : Common API for large molecular database, RADIS.</title><link>http://openastronomy.org/Universe_OA/posts/2023/05/20230508_1207_menasrac/</link><dc:creator>Racim MENASRIA</dc:creator><description>&lt;h4&gt;Blog GSoC project : Common API for large molecular database, RADIS.&lt;/h4&gt;&lt;p&gt;Hello, I’m Racim MENASRIA a French engineering student at CentraleSupelec. I m glad to take part in the 2023 GSoC programm to contribute to Radis, a fast line-by-line code for high-resolution infrared molecular spectra.&lt;/p&gt;
&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/200/0*GIeb_J5QTLrhtfNj"&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img alt="" src="https://cdn-images-1.medium.com/max/250/0*bNLY4YMhDxf2yxek"&gt;&lt;/figure&gt;&lt;p&gt;This blog will be used to post my results, remarks, difficulties or annything I consider useful to document my work.&lt;/p&gt;
&lt;p&gt;I’m looking forward to stard contributing :)&lt;/p&gt;
&lt;!-- TEASER_END --&gt;
&lt;img alt="" height="1" src="https://medium.com/_/stat?event=post.clientViewed&amp;amp;referrerSource=full_rss&amp;amp;postId=10c7a1c786e4" width="1"&gt;</description><category>radis</category><guid>http://openastronomy.org/Universe_OA/posts/2023/05/20230508_1207_menasrac/</guid><pubDate>Mon, 08 May 2023 11:07:08 GMT</pubDate></item></channel></rss>