 <?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.analytica.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lchrisman</id>
	<title>Analytica Docs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.analytica.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lchrisman"/>
	<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php/Special:Contributions/Lchrisman"/>
	<updated>2026-07-03T18:09:26Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.9</generator>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Read_data_from_URL_on_internet&amp;diff=64054</id>
		<title>Read data from URL on internet</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Read_data_from_URL_on_internet&amp;diff=64054"/>
		<updated>2026-07-02T22:15:18Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* See Also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Analytica User Guide]]&lt;br /&gt;
&amp;lt;breadcrumbs&amp;gt;Analytica User Guide &amp;gt; Integration with data and applications &amp;gt; {{PAGENAME}}&amp;lt;/breadcrumbs&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The [[ReadFromUrl]] function, on the Database menu, reads text from URL sources, such as HTTP web pages or FTP sites.&lt;br /&gt;
&lt;br /&gt;
''This feature is available in {{Analytica Developer}}  and [[Optimizer]].''&lt;br /&gt;
&lt;br /&gt;
==ReadFromUrl(url, ''method, formValues, formFields, formIndex'')==&lt;br /&gt;
&lt;br /&gt;
[[ReadFromUrl]] reads text or images from a URL (Universal Resource Locator) location on the web. In most cases, ypu can call it with a single parameter -- the URL. When reading from a web page, the «url» should begin with &amp;lt;nowiki&amp;gt;'http://....'&amp;lt;/nowiki&amp;gt;. When reading a text file from an FTP site, it should begin with &amp;lt;nowiki&amp;gt;'ftp://...'&amp;lt;/nowiki&amp;gt;. It returns the entire text as a text value. In most cases, you will need to write Analytica expressions to parse the data. When the URL is an http request that points to an image (*.jpg, *.png, *.gif, etc), it returns a picture object, which you can assign to the Pict attribute of objects, or into an array. With the exception of http requests to known image types, the source data must be textual, and if not, the resulting data will be garbled.&lt;br /&gt;
&lt;br /&gt;
Some web pages and most FTP sites require user and password authentication to access. To authenticate, embed the user name and password in the URL, like this:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;ReadFromUrl(&amp;lt;nowiki&amp;gt;'http://user:password@www.site.com/dir/page.htm'&amp;lt;/nowiki&amp;gt;)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;ReadFromUrl(&amp;lt;nowiki&amp;gt;'ftp://user:password@site.com/directory/file.txt'&amp;lt;/nowiki&amp;gt;)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The optional second through fourth parameters are used to submit data to web forms. There are two methods used to submit data to HTTP web forms: &amp;lt;code&amp;gt;method: 'POST'&amp;lt;/code&amp;gt;or &amp;lt;code&amp;gt;method: 'GET'&amp;lt;/code&amp;gt;. The field names and the values submitted for those fields are specified in «formValues» and «formFields», which must share a common index, and if that common index is anything other than «formFields», it should be specified in the «formIndex» parameter.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ReadFromUrl]]&lt;br /&gt;
* [[OAuth2Authorize]]&lt;br /&gt;
* [[OpenURL]]&lt;br /&gt;
* [[Links or URL in model attributes]]&lt;br /&gt;
* [[Retrieving Content From the Web]]&lt;br /&gt;
* [[Excel spreadsheets read and write]]&lt;br /&gt;
* [[Read and write text files]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;footer&amp;gt;Excel spreadsheets read and write / {{PAGENAME}} / Import and Export data&amp;lt;/footer&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=64043</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=64043"/>
		<updated>2026-06-29T22:39:15Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Assista */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; &amp;lt;!--Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analytica release 7.1 is currently in early [[Beta Tester Page|Beta Testing]].  If have have a paid desktop Analytica subscription, we encourage you to try it out from the [[Beta Tester Page]].&lt;br /&gt;
&lt;br /&gt;
== Highlights of Analytica 7.1 ==&lt;br /&gt;
[[File:Assista What kinds of things can you do.png|alt=Assista dialog screen answering &amp;quot;What kinds of things can you do?&amp;quot;|thumb|441x441px]]&lt;br /&gt;
'''[[#Assista|Assista]]:''' By far the most important visible improvement is in [[#Assista|Assista]], Analytica's A.I. assistant.  When first released in Analytica 6.5, Assista was already quite useful for explaining Analytica features, describing and documenting models, and building models, but it was a bit unreliable in Analytica syntax and arranging influence diagrams.  We think you will find that the latest Assista is so much improved, including writing Analytica Definitions and drawing influence diagrams. You may start to use chatting with Assista as the primary way you interact with Analytica. &lt;br /&gt;
&lt;br /&gt;
Other improvements include faster response time, better look and feel, a trace of its thinking, the ability to save and use conversations from previous sessions, ingesting files to provide information, including txt, pdf, csv, xlsx; understanding images and diagrams; a set of skills that you can extend and customize, and more. &lt;br /&gt;
&lt;br /&gt;
'''[[#Engine|Performance]]:'''  Large models start up much faster using multiple processes to parse the definitions. Arrays now use a ''tensor'' representation, similar to AI frameworks like PyTorch and TensorFlow, but with Index labels that support &amp;quot;Intelligent Arrays&amp;quot;. This internal improvement isn't noticeable to users -- but enables major future performance improvements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''[[#Spreadsheets|CSV and spreadsheet files]] :'''  You can now import [[#CSV files|CSV files]] simply by dragging them into an diagram or in a command line when you start Analytica. You can create a new [[#spreadsheets |spreadsheet]]  with and add or remove sheets from it.&lt;br /&gt;
&lt;br /&gt;
'''[[#Spanish|Spanish]]:'''  The user interface now supports Spanish -- with other languages in the future. Assista already supports most languages, and explains features (translating docs) in your language.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* You can add, drag-and-drop or paste an image into the chat, which she can see while processing your question. For example, she can extract data from the image.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
* You can have Assista generate a report as a downloadable PDF or Word document, which can contain graphs or other images from your model and formatted equations.&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is far more flexible. You can use it to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
* There is a new option, '''Use as default arrow style''', on the right-mouse context menu for an influence diagram arrow. This sets the global arrow style default to match the selected arrow.&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image. Also there is a new «maxCells» parameter that can be used to prevent giagantic arrays from being encoded (resulting in immensely long text).&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
* Added a syntax construct for [[Namespaces#Scoped_namespace_inclusion:_Using|Scoped namespace inclusion]] to bring a namespace into scope for only a localized expression or lexical block.&lt;br /&gt;
* File functions ([[ReadTextFile]], [[WriteTextFile]], [[ReadBinaryFile]], [[WriteBinaryFile]], [[ReadImageFile]] and [[WriteImageFile]]) have a new optional parameter, «extensionFilter», where you can specify which extension filters show up on a file selector dialog.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (the deprecated version used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=64042</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=64042"/>
		<updated>2026-06-29T22:35:47Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Built-in functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; &amp;lt;!--Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Analytica release 7.1 is currently in early [[Beta Tester Page|Beta Testing]].  If have have a paid desktop Analytica subscription, we encourage you to try it out from the [[Beta Tester Page]].&lt;br /&gt;
&lt;br /&gt;
== Highlights of Analytica 7.1 ==&lt;br /&gt;
[[File:Assista What kinds of things can you do.png|alt=Assista dialog screen answering &amp;quot;What kinds of things can you do?&amp;quot;|thumb|441x441px]]&lt;br /&gt;
'''[[#Assista|Assista]]:''' By far the most important visible improvement is in [[#Assista|Assista]], Analytica's A.I. assistant.  When first released in Analytica 6.5, Assista was already quite useful for explaining Analytica features, describing and documenting models, and building models, but it was a bit unreliable in Analytica syntax and arranging influence diagrams.  We think you will find that the latest Assista is so much improved, including writing Analytica Definitions and drawing influence diagrams. You may start to use chatting with Assista as the primary way you interact with Analytica. &lt;br /&gt;
&lt;br /&gt;
Other improvements include faster response time, better look and feel, a trace of its thinking, the ability to save and use conversations from previous sessions, ingesting files to provide information, including txt, pdf, csv, xlsx; understanding images and diagrams; a set of skills that you can extend and customize, and more. &lt;br /&gt;
&lt;br /&gt;
'''[[#Engine|Performance]]:'''  Large models start up much faster using multiple processes to parse the definitions. Arrays now use a ''tensor'' representation, similar to AI frameworks like PyTorch and TensorFlow, but with Index labels that support &amp;quot;Intelligent Arrays&amp;quot;. This internal improvement isn't noticeable to users -- but enables major future performance improvements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''[[#Spreadsheets|CSV and spreadsheet files]] :'''  You can now import [[#CSV files|CSV files]] simply by dragging them into an diagram or in a command line when you start Analytica. You can create a new [[#spreadsheets |spreadsheet]]  with and add or remove sheets from it.&lt;br /&gt;
&lt;br /&gt;
'''[[#Spanish|Spanish]]:'''  The user interface now supports Spanish -- with other languages in the future. Assista already supports most languages, and explains features (translating docs) in your language.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is far more flexible. You can use it to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
* There is a new option, '''Use as default arrow style''', on the right-mouse context menu for an influence diagram arrow. This sets the global arrow style default to match the selected arrow.&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image. Also there is a new «maxCells» parameter that can be used to prevent giagantic arrays from being encoded (resulting in immensely long text).&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
* Added a syntax construct for [[Namespaces#Scoped_namespace_inclusion:_Using|Scoped namespace inclusion]] to bring a namespace into scope for only a localized expression or lexical block.&lt;br /&gt;
* File functions ([[ReadTextFile]], [[WriteTextFile]], [[ReadBinaryFile]], [[WriteBinaryFile]], [[ReadImageFile]] and [[WriteImageFile]]) have a new optional parameter, «extensionFilter», where you can specify which extension filters show up on a file selector dialog.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (the deprecated version used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=WriteImageFile&amp;diff=64041</id>
		<title>WriteImageFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=WriteImageFile&amp;diff=64041"/>
		<updated>2026-06-29T20:02:37Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document extensionFilter parameter (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Image and canvas functions]]&lt;br /&gt;
[[Category:Database Functions]]&lt;br /&gt;
[[category:File system functions]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
''New to [[Analytica 5.0]]''&lt;br /&gt;
&lt;br /&gt;
''Requires {{Analytica Developer}} edition or better.''&lt;br /&gt;
&lt;br /&gt;
== WriteImageFile( filename, image'', showDialog, warn, mimeType, title{{Release|6.0||, download}}{{Release|7.1||, extensionFilter}}'' ) ==&lt;br /&gt;
&lt;br /&gt;
Writes an in-memory image to a file.&lt;br /&gt;
&lt;br /&gt;
* «filename»: When a full (absolute) filename is not supplied, the file name is relative to the [[CurrentDataFolder]]. {{Release|6.4||&lt;br /&gt;
*:When «filename» is &amp;lt;code&amp;gt;&amp;quot;&amp;lt;&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;, the image is written to an in-memory binary data term.}}&lt;br /&gt;
* «image»: An image, obtained from the &amp;lt;code&amp;gt;(Pict Of «obj»)&amp;lt;/code&amp;gt; attribute, or from a function that returns an image such as [[ReadImageFile]], [[ReadFromUrl]], or [[CanvasImage]].&lt;br /&gt;
* «showDialog»: (Optional) When &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;, the file finder dialog is always presented to the user. When &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;, the dialog is never presented to the user. When omitted, the dialog is shown only if the file cannot be written to «filename», or if the file already exists and you haven't specified &amp;lt;code&amp;gt;warn:False&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «warn»: (Optional) When &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;, a warning is issued if &amp;lt;code&amp;gt;showDialog:False&amp;lt;/code&amp;gt; and the file exists. This warning will only be shown when [[Preferences#Show result warnings|Show Result Warnings]] is enabled.&lt;br /&gt;
* «mimeType»: (Optional) Specifies the preferred file type, such as &amp;lt;code&amp;gt;'PNG'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'JPG'&amp;lt;/code&amp;gt;, etc., for the image.&lt;br /&gt;
* «title»: (Optional) A custom caption shown in the file selector when the file selector is displayed.{{Release|6.0||&lt;br /&gt;
* «download»: (Option) When &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; and running in [[ACP]], the image downloaded to the end user's computer as an image file with the name «filename».}}&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
* «extensionFilter»: (Optional) Overrides the file types offered in the file-selector dialog. Specify the filter(s) as a text in any of these forms: a ''display-format'' text such as &amp;lt;code&amp;gt;&amp;quot;Image Files (*.png, *.jpg, *.tif); All Files (*.*)&amp;quot;&amp;lt;/code&amp;gt;; a list of &amp;lt;code&amp;gt;&amp;quot;Description{{!}}patterns&amp;quot;&amp;lt;/code&amp;gt; filters such as &amp;lt;code&amp;gt;[&amp;quot;Images{{!}}*.png;*.jpg;*.tif&amp;quot;, &amp;quot;All files{{!}}*.*&amp;quot;]&amp;lt;/code&amp;gt;; or just patterns such as &amp;lt;code&amp;gt;&amp;quot;*.png;*.jpg;*.gif;*.tif&amp;quot;&amp;lt;/code&amp;gt;. An &amp;lt;code&amp;gt;&amp;quot;All files (*.*)&amp;quot;&amp;lt;/code&amp;gt; entry is appended automatically unless your list already includes one; when omitted, the default file types are shown.}}&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ReadImageFile]]&lt;br /&gt;
* [[ReadFromURL]]&lt;br /&gt;
* [[CanvasImage]]&lt;br /&gt;
* [[ImageInfo]]{{Release|6.4||&lt;br /&gt;
* If you write to an in-memory binary data term, see: [[ReadBinaryFile]], [[GetFromBinaryData]], [[BinaryDataSize]]}}&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=ReadImageFile&amp;diff=64040</id>
		<title>ReadImageFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=ReadImageFile&amp;diff=64040"/>
		<updated>2026-06-29T19:59:19Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Note extensionFilter parameter added in 7.1 (ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:System Functions]]&lt;br /&gt;
[[category:Database Functions]]&lt;br /&gt;
[[Category:Image and canvas functions]]&lt;br /&gt;
 [[category:File system functions]]&lt;br /&gt;
&lt;br /&gt;
''Requires {{Analytica Developer}} or Power Player''&lt;br /&gt;
&lt;br /&gt;
== ReadImageFile(filename'', showDialog{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Reads an image file with «filename» into memory and returns a value that acts as a [[handle]] to the image and can be assigned to the [[Pict]] attribute of an object on a diagram.&lt;br /&gt;
&lt;br /&gt;
The optional parameter, «showDialog» controls whether the file dialog appears. If not specified, then the dialog appears only if the file does not exist. To prevent this from showing (displaying an error instead) specify «showDialog» as &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;. To force the dialog to display, even if the file exists (i.e., as a way to give the user a chance to change the filename, while still providing a default name), specify «showDialog» as true.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
«extensionFilter»: (Optional) Overrides the file types offered in the file-selector dialog. Specify the filter(s) as a text in any of these forms:&lt;br /&gt;
* ''Display form'' &amp;amp;mdash; one or more filters separated by semicolons, each a description with its patterns in parentheses, e.g. &amp;lt;code&amp;gt;&amp;quot;Image Files (*.png, *.jpg, *.tif); All Files (*.*)&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''A list of'' &amp;lt;code&amp;gt;&amp;quot;Description{{!}}patterns&amp;quot;&amp;lt;/code&amp;gt; ''filters'' (description first, patterns separated by &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;), e.g. &amp;lt;code&amp;gt;[&amp;quot;Images{{!}}*.png;*.jpg;*.tif&amp;quot;, &amp;quot;All files{{!}}*.*&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Just patterns'', e.g. &amp;lt;code&amp;gt;&amp;quot;*.png;*.jpg;*.gif;*.tif&amp;quot;&amp;lt;/code&amp;gt; (a description is generated automatically).&lt;br /&gt;
An &amp;lt;code&amp;gt;&amp;quot;All files (*.*)&amp;quot;&amp;lt;/code&amp;gt; entry is appended automatically unless your list already includes one. When omitted, the default file types are shown.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
From [[ADE]], the dialog is never displayed.&lt;br /&gt;
&lt;br /&gt;
== Uses ==&lt;br /&gt;
We foresee possible cases where certain applications may need to integrate with an external application that generates an image, and then may want to embed the image in a diagram.  Analytica might launch the external command using [[RunConsoleProcess]], sending it commands and data either through stdIn or via a data file, and waiting for it to complete.  The external program would produce an image (e.g., a JPEG) and store it in a file.  Analytica would then use [[ReadImageFile]] to read in the resulting, dynamically created, image and assign it to the Pict attribute of a picture node on the diagram.   To update the [[dynamic]] image, it would repeat the process.&lt;br /&gt;
&lt;br /&gt;
External processes that might be used in the fashion might include GIS systems, drawing programs, or external graphing engines.&lt;br /&gt;
&lt;br /&gt;
This reads the image only from a file on disk.  To read an image from a web URL, use [[ReadFromURL]]. There is also no facility currently for extracting &amp;quot;blobs&amp;quot; from database queries and converting them to functional image objects.&lt;br /&gt;
&lt;br /&gt;
Image handles currently display in result tables in a textual form.  This is also tentative and subject to change, with the possibility that future releases will display the graphical image directly in the result table.&lt;br /&gt;
&lt;br /&gt;
== Supported file formats ==&lt;br /&gt;
* JPG, JPEG&lt;br /&gt;
* PNG&lt;br /&gt;
* GIF&lt;br /&gt;
* TIFF&lt;br /&gt;
* EXIF&lt;br /&gt;
* WMF&lt;br /&gt;
* BMP (in [[Analytica 5.1]] or later)&lt;br /&gt;
&lt;br /&gt;
== From ADE ==&lt;br /&gt;
When evaluated in [[ADE|the Analytica Decision Engine (ADE)]] and a dialog needs to be shown to the end-user, it calls [[IAdeUICallbacks::GetFilename]](...). From within that callback, the parent application can interact with the end-user to resolve the file path, and a web applications can instruct the end-user to upload a file. Once complete, the callback returns the full path to the file which is then read. To receive this callback, the parent application must have previously registered the callback with ADE using [[CAEngine::SetCallbackObject]]( ). If it has not registered a callback and the file doesn't exist, returns an empty text.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
Introduced in [[Analytica 4.2]] as an experimental feature.&lt;br /&gt;
&lt;br /&gt;
ADE callback added in [[Analytica 4.6|ADE 4.6]]&lt;br /&gt;
&lt;br /&gt;
Promoted to supported function in [[Analytica 5.0]].&lt;br /&gt;
&lt;br /&gt;
«extensionFilter» parameter added in [[Analytica 7.1]].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ReadFromUrl]]&lt;br /&gt;
* [[ReadTextFile]]&lt;br /&gt;
* [[RunConsoleProcess]]&lt;br /&gt;
* [[Handle]]&lt;br /&gt;
* [[ImageFromHex]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=ReadImageFile&amp;diff=64039</id>
		<title>ReadImageFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=ReadImageFile&amp;diff=64039"/>
		<updated>2026-06-29T19:58:04Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document extensionFilter parameter (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:System Functions]]&lt;br /&gt;
[[category:Database Functions]]&lt;br /&gt;
[[Category:Image and canvas functions]]&lt;br /&gt;
 [[category:File system functions]]&lt;br /&gt;
&lt;br /&gt;
''Requires {{Analytica Developer}} or Power Player''&lt;br /&gt;
&lt;br /&gt;
== ReadImageFile(filename'', showDialog{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Reads an image file with «filename» into memory and returns a value that acts as a [[handle]] to the image and can be assigned to the [[Pict]] attribute of an object on a diagram.&lt;br /&gt;
&lt;br /&gt;
The optional parameter, «showDialog» controls whether the file dialog appears. If not specified, then the dialog appears only if the file does not exist. To prevent this from showing (displaying an error instead) specify «showDialog» as &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;. To force the dialog to display, even if the file exists (i.e., as a way to give the user a chance to change the filename, while still providing a default name), specify «showDialog» as true.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
«extensionFilter»: (Optional) Overrides the file types offered in the file-selector dialog. Specify the filter(s) as a text in any of these forms:&lt;br /&gt;
* ''Display form'' &amp;amp;mdash; one or more filters separated by semicolons, each a description with its patterns in parentheses, e.g. &amp;lt;code&amp;gt;&amp;quot;Image Files (*.png, *.jpg, *.tif); All Files (*.*)&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''A list of'' &amp;lt;code&amp;gt;&amp;quot;Description{{!}}patterns&amp;quot;&amp;lt;/code&amp;gt; ''filters'' (description first, patterns separated by &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;), e.g. &amp;lt;code&amp;gt;[&amp;quot;Images{{!}}*.png;*.jpg;*.tif&amp;quot;, &amp;quot;All files{{!}}*.*&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Just patterns'', e.g. &amp;lt;code&amp;gt;&amp;quot;*.png;*.jpg;*.gif;*.tif&amp;quot;&amp;lt;/code&amp;gt; (a description is generated automatically).&lt;br /&gt;
An &amp;lt;code&amp;gt;&amp;quot;All files (*.*)&amp;quot;&amp;lt;/code&amp;gt; entry is appended automatically unless your list already includes one. When omitted, the default file types are shown.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
From [[ADE]], the dialog is never displayed.&lt;br /&gt;
&lt;br /&gt;
== Uses ==&lt;br /&gt;
We foresee possible cases where certain applications may need to integrate with an external application that generates an image, and then may want to embed the image in a diagram.  Analytica might launch the external command using [[RunConsoleProcess]], sending it commands and data either through stdIn or via a data file, and waiting for it to complete.  The external program would produce an image (e.g., a JPEG) and store it in a file.  Analytica would then use [[ReadImageFile]] to read in the resulting, dynamically created, image and assign it to the Pict attribute of a picture node on the diagram.   To update the [[dynamic]] image, it would repeat the process.&lt;br /&gt;
&lt;br /&gt;
External processes that might be used in the fashion might include GIS systems, drawing programs, or external graphing engines.&lt;br /&gt;
&lt;br /&gt;
This reads the image only from a file on disk.  To read an image from a web URL, use [[ReadFromURL]]. There is also no facility currently for extracting &amp;quot;blobs&amp;quot; from database queries and converting them to functional image objects.&lt;br /&gt;
&lt;br /&gt;
Image handles currently display in result tables in a textual form.  This is also tentative and subject to change, with the possibility that future releases will display the graphical image directly in the result table.&lt;br /&gt;
&lt;br /&gt;
== Supported file formats ==&lt;br /&gt;
* JPG, JPEG&lt;br /&gt;
* PNG&lt;br /&gt;
* GIF&lt;br /&gt;
* TIFF&lt;br /&gt;
* EXIF&lt;br /&gt;
* WMF&lt;br /&gt;
* BMP (in [[Analytica 5.1]] or later)&lt;br /&gt;
&lt;br /&gt;
== From ADE ==&lt;br /&gt;
When evaluated in [[ADE|the Analytica Decision Engine (ADE)]] and a dialog needs to be shown to the end-user, it calls [[IAdeUICallbacks::GetFilename]](...). From within that callback, the parent application can interact with the end-user to resolve the file path, and a web applications can instruct the end-user to upload a file. Once complete, the callback returns the full path to the file which is then read. To receive this callback, the parent application must have previously registered the callback with ADE using [[CAEngine::SetCallbackObject]]( ). If it has not registered a callback and the file doesn't exist, returns an empty text.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
Introduced in [[Analytica 4.2]] as an experimental feature. &lt;br /&gt;
&lt;br /&gt;
ADE callback added in [[Analytica 4.6|ADE 4.6]]&lt;br /&gt;
&lt;br /&gt;
Promoted to supported function in [[Analytica 5.0]].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ReadFromUrl]]&lt;br /&gt;
* [[ReadTextFile]]&lt;br /&gt;
* [[RunConsoleProcess]]&lt;br /&gt;
* [[Handle]]&lt;br /&gt;
* [[ImageFromHex]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=WriteBinaryFile&amp;diff=64038</id>
		<title>WriteBinaryFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=WriteBinaryFile&amp;diff=64038"/>
		<updated>2026-06-29T19:55:12Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document extensionFilter parameter (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Database Functions]]&lt;br /&gt;
[[category:System Functions]]&lt;br /&gt;
[[category:File system functions]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
''Requires [[Analytica 5.0]] {{Developer}} edition or better.''&lt;br /&gt;
&lt;br /&gt;
ReadBinaryFile() and WriteBinaryFile()  read and write binary files, in contrast to  [[ReadTextFile]] and  [[WriteTextFile]], which read and write text files (surprise!). Binary files store data in a format similar to how the data are represented in computer memory used by Analytica (or any application).  So they are usually more compact and much faster to read or write than text files. Text files, such as [[ParseCSV|CSV files]] or Analytica [[Model file formats]], represent each number as a sequence of digit characters, which have to be parsed and converted to the internal binary form, which takes time.  &lt;br /&gt;
&lt;br /&gt;
Of course,  binary files, unlike text files, are not readable by humans. The layout and metadata, such as the size of each cell and row, and the number of rows, is not part of a binary file. This is unlike CSV files, for example, with separators for each cell and row (usually comma and new line), and column headers in the first row.  For binary files, you must need to specify this information as parameters to ReadBinaryFile() and WriteBinaryFile(), including  array indexes, and the data type or number of bytes per cell. It's usually worth using binary formats only when you have really large amounts of data so that the file size and read/write speed are significant issues. Occasionally, you may want to read binary files from other sources or generate binary files for use by other applications. &lt;br /&gt;
&lt;br /&gt;
== WriteBinaryFile(filename, data'', I..., bytesPer, typeFlags, append, warn, showDialog, title{{Release|6.0||, download}}{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Writes data to a binary file. If you wish to write data to a human-readable file, you should probably be using [[WriteTextFile]]. Use [[WriteBinaryFile]] when providing data for or integrated with another application that has a specific binary data format. Or when you have large amounts of data -- e.g. large arrays -- to save and read into Analytica, you can save substantial computation time, reduce file size, and retain full precision by using [[WriteBinaryFile]] and [[ReadBinaryFile]] relative to using text files or a database.&lt;br /&gt;
&lt;br /&gt;
== Parameters ==&lt;br /&gt;
=== filename ===&lt;br /&gt;
Name of file to create, replace or append to. &lt;br /&gt;
&lt;br /&gt;
File name paths can be either relative or absolute. An absolute path specifies the full path of the file from a root drive, such as &lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;C:\Users\Drice\Documents\Projects\FatigueAnalysis\Results.bin&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A relative filename incompletely specifies a file path, and is interpreted relative to the [[CurrentDataDirectory]]. &lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||If you set the «filename» to &amp;lt;code&amp;gt;&amp;quot;&amp;lt;&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;, [[WriteBinaryFile]] writes to an in-memory binary data term rather than to a file. }}&lt;br /&gt;
&lt;br /&gt;
=== data === &lt;br /&gt;
The data to write, usually an array. If «data» is an array of integers from 0 to 255, by default each integer is written into one byte of the file. If the number is a real (floating point) number, it will round it to an integer, and ignore digits above 255 (the maximum integer that fits into one byte). To write larger integers or to preserve floating point numbers or text values, you can specify more bytes  and other types with the optional «bytesPer» and «typeFlags» described below.&lt;br /&gt;
&lt;br /&gt;
===  I... ===&lt;br /&gt;
The indexes of the array passed to «data». When «data» has more than one dimension, the order in which you list the indexes controls the order in which cells are written to the file.  The first index you list is varied the slowest, and the last index you list varies fastest.  For example, suppose index &amp;lt;code&amp;gt;I := 1..3&amp;lt;/code&amp;gt; and index &amp;lt;code&amp;gt;J := 1..2&amp;lt;/code&amp;gt;, then &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;WriteBinaryFile(filename, data, I, J)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
writes the cells in the order:&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whereas &lt;br /&gt;
:&amp;lt;code&amp;gt;WriteBinaryFile(filename, data, J, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
writes the cells in the order&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== bytesPer ===&lt;br /&gt;
&lt;br /&gt;
The number of bytes in the file per cell of «data». &lt;br /&gt;
&lt;br /&gt;
When writing integer values (the default when «typeFlags» is omitted), this specifies the number of bytes per integer word, and can be 1 (for single bytes, integers 0 to 2^8-1=255), 2 (for integers up to 2^16-1 = 65,535), 4 (for 32-bit integers up to 2^32-1 = 4,294,967,295) or 8 (for 64-bit integers up to 2^64-1).&lt;br /&gt;
&lt;br /&gt;
For floating point real numbers, you can specify 4 (for 32-bit IEEE 754 reals, often called '''''float'''''s), or 8 (for 64-bit IEEE 754 reals, often called '''''double'''''s). When «typeFlags» = 2 (floating point), the  «bytesPer» defaults to 8 if not specified.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;, it uses 9 bytes per item, so you can either omit «bytesPer» or set it to 9. Any other value gives an error.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;, the number of bytes per item may vary (depending on the length of text values), and you must omit «bytesPer» to avoid an error.&lt;br /&gt;
&lt;br /&gt;
=== typeFlags ===&lt;br /&gt;
&lt;br /&gt;
The data type format written:&lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; = Integer (default)&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; = IEEE 754 Floating point real&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; = Value (numbers, dates and null). 9 bytes per item.&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; = Value (including text{{Release|6.2|| and binary}}). Variable bytes per text item.{{Release|1=6.2|2=|3=&lt;br /&gt;
:&amp;lt;code&amp;gt;7&amp;lt;/code&amp;gt; = Raw binary data. «data» must be in-memory binary data.}}&lt;br /&gt;
:&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt; = Big endian flag. &lt;br /&gt;
:&amp;lt;code&amp;gt;64&amp;lt;/code&amp;gt; = Flag to issue error when cell cannot be coerced to type. By default, it will not give error messages when it cannot coerce a cell to fit in the specified data type.&lt;br /&gt;
&lt;br /&gt;
A standard Intel convention writes numbers (integers or floating point values) with the least significant bytes written first, least significant bytes last, which is termed &amp;quot;little-endian format&amp;quot;.  [[WriteBinaryFile]]  uses this default unless the &amp;lt;code&amp;gt;typeFlags = 32&amp;lt;/code&amp;gt; flag is specified. &amp;quot;Big endian&amp;quot; means that the most significant byte is written first.&lt;br /&gt;
&lt;br /&gt;
You can add &amp;lt;code&amp;gt;32, 64&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;32 + 64&amp;lt;/code&amp;gt; options to the data type selection. So, for example, a value of &amp;lt;code&amp;gt;2 + 32 + 64&amp;lt;/code&amp;gt; would specify a floating point format (&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;) with the byte order reversed (&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt;), and with an error issued when a non-numeric cell is encountered (&amp;lt;code&amp;gt;64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Integer formats write the «bytesPer» least-significant bits to the file. For example, when «bytesPer» is 2, the integers written will be between 0 and 65535 (or between -32768 and 32767).  If «data» contains a number outside this range, such as 66,000, then &amp;lt;code&amp;gt;Mod(66K, 2^16, true)&amp;lt;/code&amp;gt;, which equals 464 would actually be written. It isn't necessary to differentiate between whether the integers are positive or negative at the time they are being written, but you do need to make this distinction when reading (see [[ReadBinaryFile]]).&lt;br /&gt;
&lt;br /&gt;
The Value type is a variant data type, in which a byte is written to encode the internal data type of the value, and followed by an 8-byte value. The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; only writes Analytica data types that can be fully encoded in with 8 bytes, which includes integers, fixed-point reals, floating point reals, date and date-time numbers, and the special value [[Null]]. When using this type, [[Null]] values ARE written to the file.  The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; cannot be used to write text values, since these vary in length. The cells will each use 9 bytes, and will be spaced every 9 bytes in the file.&lt;br /&gt;
&lt;br /&gt;
The «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; extends option &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; by allowing text values and binary data (&amp;quot;blobs&amp;quot;). When a text value occurs, the first byte indicates that the value is text, the next four bytes encode the length, &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt;, and the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; bytes encodes the characters in UTF-8. {{Release|6.2||When a binary &amp;quot;blob&amp;quot; occurs, the first byte indicates that it is binary data, the next 8 bytes encode the number of bytes, and the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt;bytes are the binary data.}}  When this format is used, the «bytesPer» parameter must be omitted. The location of items in the file are not spaced at any predictable interval, since text items vary in length.&lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||When «typeFlags» is &amp;lt;code&amp;gt;7&amp;lt;/code&amp;gt;, then «data» must be in memory binary data or Null (if Null, the data is ignored). This writes the binary data directly with no extra surrounding information to indicate its type or size. Thus, if this option is applied to an array of binary data, the binary data gets directly appended.}}&lt;br /&gt;
&lt;br /&gt;
=== append ===&lt;br /&gt;
When you pass &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; to the «append» parameter, it appends the data to the end of the file if it already exists. When you omit «append» or set it to false, it overwrites any existing file with the new contents.&lt;br /&gt;
&lt;br /&gt;
=== warn ===&lt;br /&gt;
Use this Boolean parameter to force or suppress a warning when the file already exists. When omitted, a warning occurs unless you are appending.&lt;br /&gt;
&lt;br /&gt;
=== showDialog ===&lt;br /&gt;
This is a flag to force or suppress the file selector dialog. When not specified, the dialog only displays if needed, for example, if the file name is blank or to a directory that is not writable or does not exist. Setting «showDialog» to false suppresses the dialog from appearing. Setting «showDialog» to true forces the dialog to display, using «filename» as the initial default.&lt;br /&gt;
&lt;br /&gt;
=== title ===&lt;br /&gt;
The text to use as caption of file selector dialog.&lt;br /&gt;
&lt;br /&gt;
=== download ===&lt;br /&gt;
''New to [[Analytica 6.0]]''&lt;br /&gt;
&lt;br /&gt;
When set to &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; and the model is running in [[ACP]], the data is downloaded to the end user's computer as a file with the name given by «filename».&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
=== extensionFilter ===&lt;br /&gt;
(''New in [[Analytica 7.1]]'') Overrides the file types offered in the file-selector dialog. Specify the filter(s) as a text in any of these forms:&lt;br /&gt;
* ''Display form'' &amp;amp;mdash; one or more filters separated by semicolons, each a description with its patterns in parentheses, e.g. &amp;lt;code&amp;gt;&amp;quot;Data Files (*.dat, *.bin); All Files (*.*)&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''A list of'' &amp;lt;code&amp;gt;&amp;quot;Description{{!}}patterns&amp;quot;&amp;lt;/code&amp;gt; ''filters'' (description first, patterns separated by &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;), e.g. &amp;lt;code&amp;gt;[&amp;quot;Data files{{!}}*.dat;*.bin&amp;quot;, &amp;quot;All files{{!}}*.*&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Just patterns'', e.g. &amp;lt;code&amp;gt;&amp;quot;*.dat;*.bin&amp;quot;&amp;lt;/code&amp;gt; (a description is generated automatically).&lt;br /&gt;
An &amp;lt;code&amp;gt;&amp;quot;All files (*.*)&amp;quot;&amp;lt;/code&amp;gt; entry is appended automatically unless your list already includes one. When omitted, the default file types are shown.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[In-memory binary data terms]]&lt;br /&gt;
* [[Binary and hexadecimal integer formats]]&lt;br /&gt;
* [[ReadBinaryFile]]&lt;br /&gt;
* [[GetFromBinaryData]]&lt;br /&gt;
* [[BinaryDataSize]]&lt;br /&gt;
* [[Base64-encoded binary term literals]]&lt;br /&gt;
* [[WriteTextFile]]&lt;br /&gt;
* [[Dec2Bin]]&lt;br /&gt;
* [[Hex2Dec]]&lt;br /&gt;
* [[Hex2Bin]]&lt;br /&gt;
* [[Bin2Dec]]&lt;br /&gt;
* [[Bin2Hex]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=WriteBinaryFile&amp;diff=64037</id>
		<title>WriteBinaryFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=WriteBinaryFile&amp;diff=64037"/>
		<updated>2026-06-29T19:53:03Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Add extensionFilter to signature (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Database Functions]]&lt;br /&gt;
[[category:System Functions]]&lt;br /&gt;
[[category:File system functions]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
''Requires [[Analytica 5.0]] {{Developer}} edition or better.''&lt;br /&gt;
&lt;br /&gt;
ReadBinaryFile() and WriteBinaryFile()  read and write binary files, in contrast to  [[ReadTextFile]] and  [[WriteTextFile]], which read and write text files (surprise!). Binary files store data in a format similar to how the data are represented in computer memory used by Analytica (or any application).  So they are usually more compact and much faster to read or write than text files. Text files, such as [[ParseCSV|CSV files]] or Analytica [[Model file formats]], represent each number as a sequence of digit characters, which have to be parsed and converted to the internal binary form, which takes time.  &lt;br /&gt;
&lt;br /&gt;
Of course,  binary files, unlike text files, are not readable by humans. The layout and metadata, such as the size of each cell and row, and the number of rows, is not part of a binary file. This is unlike CSV files, for example, with separators for each cell and row (usually comma and new line), and column headers in the first row.  For binary files, you must need to specify this information as parameters to ReadBinaryFile() and WriteBinaryFile(), including  array indexes, and the data type or number of bytes per cell. It's usually worth using binary formats only when you have really large amounts of data so that the file size and read/write speed are significant issues. Occasionally, you may want to read binary files from other sources or generate binary files for use by other applications. &lt;br /&gt;
&lt;br /&gt;
== WriteBinaryFile(filename, data'', I..., bytesPer, typeFlags, append, warn, showDialog, title{{Release|6.0||, download}}{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Writes data to a binary file. If you wish to write data to a human-readable file, you should probably be using [[WriteTextFile]]. Use [[WriteBinaryFile]] when providing data for or integrated with another application that has a specific binary data format. Or when you have large amounts of data -- e.g. large arrays -- to save and read into Analytica, you can save substantial computation time, reduce file size, and retain full precision by using [[WriteBinaryFile]] and [[ReadBinaryFile]] relative to using text files or a database.&lt;br /&gt;
&lt;br /&gt;
== Parameters ==&lt;br /&gt;
=== filename ===&lt;br /&gt;
Name of file to create, replace or append to. &lt;br /&gt;
&lt;br /&gt;
File name paths can be either relative or absolute. An absolute path specifies the full path of the file from a root drive, such as &lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;C:\Users\Drice\Documents\Projects\FatigueAnalysis\Results.bin&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A relative filename incompletely specifies a file path, and is interpreted relative to the [[CurrentDataDirectory]]. &lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||If you set the «filename» to &amp;lt;code&amp;gt;&amp;quot;&amp;lt;&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;, [[WriteBinaryFile]] writes to an in-memory binary data term rather than to a file. }}&lt;br /&gt;
&lt;br /&gt;
=== data === &lt;br /&gt;
The data to write, usually an array. If «data» is an array of integers from 0 to 255, by default each integer is written into one byte of the file. If the number is a real (floating point) number, it will round it to an integer, and ignore digits above 255 (the maximum integer that fits into one byte). To write larger integers or to preserve floating point numbers or text values, you can specify more bytes  and other types with the optional «bytesPer» and «typeFlags» described below.&lt;br /&gt;
&lt;br /&gt;
===  I... ===&lt;br /&gt;
The indexes of the array passed to «data». When «data» has more than one dimension, the order in which you list the indexes controls the order in which cells are written to the file.  The first index you list is varied the slowest, and the last index you list varies fastest.  For example, suppose index &amp;lt;code&amp;gt;I := 1..3&amp;lt;/code&amp;gt; and index &amp;lt;code&amp;gt;J := 1..2&amp;lt;/code&amp;gt;, then &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;WriteBinaryFile(filename, data, I, J)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
writes the cells in the order:&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
whereas &lt;br /&gt;
:&amp;lt;code&amp;gt;WriteBinaryFile(filename, data, J, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
writes the cells in the order&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 1, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 2, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;data[I = 3, J = 2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== bytesPer ===&lt;br /&gt;
&lt;br /&gt;
The number of bytes in the file per cell of «data». &lt;br /&gt;
&lt;br /&gt;
When writing integer values (the default when «typeFlags» is omitted), this specifies the number of bytes per integer word, and can be 1 (for single bytes, integers 0 to 2^8-1=255), 2 (for integers up to 2^16-1 = 65,535), 4 (for 32-bit integers up to 2^32-1 = 4,294,967,295) or 8 (for 64-bit integers up to 2^64-1).&lt;br /&gt;
&lt;br /&gt;
For floating point real numbers, you can specify 4 (for 32-bit IEEE 754 reals, often called '''''float'''''s), or 8 (for 64-bit IEEE 754 reals, often called '''''double'''''s). When «typeFlags» = 2 (floating point), the  «bytesPer» defaults to 8 if not specified.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;, it uses 9 bytes per item, so you can either omit «bytesPer» or set it to 9. Any other value gives an error.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;, the number of bytes per item may vary (depending on the length of text values), and you must omit «bytesPer» to avoid an error.&lt;br /&gt;
&lt;br /&gt;
=== typeFlags ===&lt;br /&gt;
&lt;br /&gt;
The data type format written:&lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; = Integer (default)&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; = IEEE 754 Floating point real&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; = Value (numbers, dates and null). 9 bytes per item.&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; = Value (including text{{Release|6.2|| and binary}}). Variable bytes per text item.{{Release|1=6.2|2=|3=&lt;br /&gt;
:&amp;lt;code&amp;gt;7&amp;lt;/code&amp;gt; = Raw binary data. «data» must be in-memory binary data.}}&lt;br /&gt;
:&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt; = Big endian flag. &lt;br /&gt;
:&amp;lt;code&amp;gt;64&amp;lt;/code&amp;gt; = Flag to issue error when cell cannot be coerced to type. By default, it will not give error messages when it cannot coerce a cell to fit in the specified data type.&lt;br /&gt;
&lt;br /&gt;
A standard Intel convention writes numbers (integers or floating point values) with the least significant bytes written first, least significant bytes last, which is termed &amp;quot;little-endian format&amp;quot;.  [[WriteBinaryFile]]  uses this default unless the &amp;lt;code&amp;gt;typeFlags = 32&amp;lt;/code&amp;gt; flag is specified. &amp;quot;Big endian&amp;quot; means that the most significant byte is written first.&lt;br /&gt;
&lt;br /&gt;
You can add &amp;lt;code&amp;gt;32, 64&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;32 + 64&amp;lt;/code&amp;gt; options to the data type selection. So, for example, a value of &amp;lt;code&amp;gt;2 + 32 + 64&amp;lt;/code&amp;gt; would specify a floating point format (&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;) with the byte order reversed (&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt;), and with an error issued when a non-numeric cell is encountered (&amp;lt;code&amp;gt;64&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Integer formats write the «bytesPer» least-significant bits to the file. For example, when «bytesPer» is 2, the integers written will be between 0 and 65535 (or between -32768 and 32767).  If «data» contains a number outside this range, such as 66,000, then &amp;lt;code&amp;gt;Mod(66K, 2^16, true)&amp;lt;/code&amp;gt;, which equals 464 would actually be written. It isn't necessary to differentiate between whether the integers are positive or negative at the time they are being written, but you do need to make this distinction when reading (see [[ReadBinaryFile]]).&lt;br /&gt;
&lt;br /&gt;
The Value type is a variant data type, in which a byte is written to encode the internal data type of the value, and followed by an 8-byte value. The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; only writes Analytica data types that can be fully encoded in with 8 bytes, which includes integers, fixed-point reals, floating point reals, date and date-time numbers, and the special value [[Null]]. When using this type, [[Null]] values ARE written to the file.  The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; cannot be used to write text values, since these vary in length. The cells will each use 9 bytes, and will be spaced every 9 bytes in the file.&lt;br /&gt;
&lt;br /&gt;
The «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; extends option &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; by allowing text values and binary data (&amp;quot;blobs&amp;quot;). When a text value occurs, the first byte indicates that the value is text, the next four bytes encode the length, &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt;, and the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; bytes encodes the characters in UTF-8. {{Release|6.2||When a binary &amp;quot;blob&amp;quot; occurs, the first byte indicates that it is binary data, the next 8 bytes encode the number of bytes, and the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt;bytes are the binary data.}}  When this format is used, the «bytesPer» parameter must be omitted. The location of items in the file are not spaced at any predictable interval, since text items vary in length.&lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||When «typeFlags» is &amp;lt;code&amp;gt;7&amp;lt;/code&amp;gt;, then «data» must be in memory binary data or Null (if Null, the data is ignored). This writes the binary data directly with no extra surrounding information to indicate its type or size. Thus, if this option is applied to an array of binary data, the binary data gets directly appended.}}&lt;br /&gt;
&lt;br /&gt;
=== append ===&lt;br /&gt;
When you pass &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; to the «append» parameter, it appends the data to the end of the file if it already exists. When you omit «append» or set it to false, it overwrites any existing file with the new contents.&lt;br /&gt;
&lt;br /&gt;
=== warn ===&lt;br /&gt;
Use this Boolean parameter to force or suppress a warning when the file already exists. When omitted, a warning occurs unless you are appending.&lt;br /&gt;
&lt;br /&gt;
=== showDialog ===&lt;br /&gt;
This is a flag to force or suppress the file selector dialog. When not specified, the dialog only displays if needed, for example, if the file name is blank or to a directory that is not writable or does not exist. Setting «showDialog» to false suppresses the dialog from appearing. Setting «showDialog» to true forces the dialog to display, using «filename» as the initial default.&lt;br /&gt;
&lt;br /&gt;
=== title ===&lt;br /&gt;
The text to use as caption of file selector dialog.&lt;br /&gt;
&lt;br /&gt;
=== download ===&lt;br /&gt;
''New to [[Analytica 6.0]]''&lt;br /&gt;
&lt;br /&gt;
When set to &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; and the model is running in [[ACP]], the data is downloaded to the end user's computer as a file with the name given by «filename».&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[In-memory binary data terms]]&lt;br /&gt;
* [[Binary and hexadecimal integer formats]]&lt;br /&gt;
* [[ReadBinaryFile]]&lt;br /&gt;
* [[GetFromBinaryData]]&lt;br /&gt;
* [[BinaryDataSize]]&lt;br /&gt;
* [[Base64-encoded binary term literals]]&lt;br /&gt;
* [[WriteTextFile]]&lt;br /&gt;
* [[Dec2Bin]]&lt;br /&gt;
* [[Hex2Dec]]&lt;br /&gt;
* [[Hex2Bin]]&lt;br /&gt;
* [[Bin2Dec]]&lt;br /&gt;
* [[Bin2Hex]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=ReadBinaryFile&amp;diff=64036</id>
		<title>ReadBinaryFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=ReadBinaryFile&amp;diff=64036"/>
		<updated>2026-06-29T19:50:19Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document extensionFilter parameter (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Database Functions]]&lt;br /&gt;
[[category:System Functions]]&lt;br /&gt;
[[category:File system functions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
''Requires [[Analytica 5.0]] {{Developer}} or higher''&lt;br /&gt;
&lt;br /&gt;
== ReadBinaryFile(filename'', bytesPer, typeFlags, offset, resultIndex..., showDialog, title{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Reads data directly from a binary (i.e., non-text) file.&lt;br /&gt;
&lt;br /&gt;
Flat data files are usually read using [[ReadTextFile]]. When you read text files, end-of-line characters are interpreted in various ways for you, conversions from character sets such as UTF-8 or Unicode may occur, and certain special byte values such as the zero byte or end-of-file cannot occur in the file. In contrast, reading from a binary file gives you access to the bytes of the file exactly as they appear.&lt;br /&gt;
&lt;br /&gt;
[[ReadBinaryFile]] is most commonly used when you have a data file in a binary data format from another application, and need to access the internal bytes at particular locations. It can also be used in conjunction with [[WriteBinaryFile]] as a fast and convenient method to dump an Analytica array to a file and load it back in later.&lt;br /&gt;
&lt;br /&gt;
The function [[GetFromBinaryData]] operates identically to [[ReadBinaryFile]], except that it reads from an in-memory binary data term rather than from a file. If you plan to run your model runs in ACP over the web, it is important to read the file into memory with one call, and then use [[GetFromBinaryData]] to read each item so that the user is asked to upload the file only once.&lt;br /&gt;
&lt;br /&gt;
== Result Value(s) ==&lt;br /&gt;
These values are returned:&lt;br /&gt;
# The contents read. &lt;br /&gt;
# The full file path&lt;br /&gt;
# The offset where it left off reading. Useful if you want to read a different data structure that starts afterwards. (new to [[Analytica 6.4]]).&lt;br /&gt;
&lt;br /&gt;
The main result returned is the contents it reads. This will either be an array indexed by the index(es) you specify in the «resultIndex» parameter, or a list of items if you omit the «resultIndex» parameter.&lt;br /&gt;
&lt;br /&gt;
To capture one or both of the other result values, use:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] ( content, path, nextOffset ) := [[ReadBinaryFile]](....)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading bytes ==&lt;br /&gt;
The usage&lt;br /&gt;
:&amp;lt;code&amp;gt;ReadBinaryFile(filename)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
returns the contents of the file as bytes, a list of integer values between 0 and 255.&lt;br /&gt;
&lt;br /&gt;
== Reading N values ==&lt;br /&gt;
To limit the number of items read, pass an index to the «resultIndex» parameter having a length equal to the maximum number of items to read. The actual number read will be less if the end-of-file is reached.  For example,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;ReadBinaryFile(filename, resultIndex: I)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parameters ==&lt;br /&gt;
==== filename ==== &lt;br /&gt;
Name of file to read from.&lt;br /&gt;
&lt;br /&gt;
File name paths can be either relative or absolute. An absolute path specifies the full path of the file from a root drive, such as &lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;C:\Users\Drice\Documents\Projects\FatigueAnalysis\Results.bin&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A relative filename incompletely specifies a file path, and is interpreted relative to the [[CurrentDataDirectory]]. &lt;br /&gt;
&lt;br /&gt;
====  I... ====&lt;br /&gt;
&lt;br /&gt;
The index(es) that you want as index(es) of the result. If you provide no index, it returns an unindexed list, so the variable calling ReadBinaryFile will appear as the index. If you provide multiple indexes, the last index listed vary fastest and first varies slowest as items are read.  &lt;br /&gt;
&lt;br /&gt;
The number of bytes to read depends on the product of the sizes of the indexes and the number of bytes per cell, which could vary if Bytesper parameter varies by one or more of the Indexes.  If the total is less than the number of bytes in the file, it will read only the amount of data needed. If the total is more than the file size, it will pad out the excess cells with NULL. &lt;br /&gt;
&lt;br /&gt;
If the indexes are in a different order in the file from the canonical order within Analytica, it reforms (transposes) the array to the internal form needed. If the amount of data is very large file (e.g. file has hundreds of MB), this reform process can be quite time-consuming.&lt;br /&gt;
&lt;br /&gt;
==== bytesPer ====&lt;br /&gt;
Specifies the number of bytes per item read. For example, when you specify &amp;lt;code&amp;gt;bytesPer: 4&amp;lt;/code&amp;gt;, then each 4 bytes becomes one cell of the result. When this is 1, then each byte is read and returned as a separate cell. Using 8 for «bytesPer» will result in the most memory-efficient encoding of contents when it is read into memory, since there is 8 times as much information per cell as would be the case for single bytes (and the bytes required per cell in memory would be the same in both cases). &lt;br /&gt;
&lt;br /&gt;
When reading integer values (as is the default when «typeFlags» is omitted), this specifies the number of bytes per integer word, and can be 1 (for single bytes), 2 (for 16-bit words), 4 (for 32-bit integers) or 8 (for 64-bit integers).&lt;br /&gt;
&lt;br /&gt;
When reading floating point real numbers, «bytesPer» can be 4 (for 32-bit IEEE 754 reals, often called '''''float'''''s), or 8 (for 64-bit IEEE 754 reals, often called '''''double'''''s). When «typeFlags» has &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; (floating point), the default for «bytesPer» is 8 if not specified.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;, nine bytes per item are used, so you can either omit «bytesPer» or set it to 9. Any other value throws an error.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;, the number of bytes per item may vary (depending on the length of text values), and so «bytesPer» must be omitted or an error will be issued.&lt;br /&gt;
&lt;br /&gt;
==== typeFlags ====&lt;br /&gt;
Controls how each item read gets converted into a value.&lt;br /&gt;
:&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; = Unsigned integer (positive only)&lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; = Signed integer (positive and negative numbers)&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; = IEEE 754 Floating point real&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; = Value (numbers, dates and null). 9 bytes per item.&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; = Value (including text{{Release|6.2|| or binary data}}). Variable bytes per text item.{{Release|6.2||&lt;br /&gt;
:&amp;lt;code&amp;gt;7&amp;lt;/code&amp;gt; {{=}} Raw binary data.&lt;br /&gt;
:&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; {{=}} image}}&lt;br /&gt;
:&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt; = Big endian flag. &lt;br /&gt;
&lt;br /&gt;
You can say the one-byte integer with hex value 0xc1 is equal to 193, or you can say that it equals -133.  The distinction here is whether you interpret the raw binary data as representing an unsigned integer (193) or a signed integer (-133). Signed integers use two's-complement so that both negative and positive values are within the possible range. Use &amp;lt;code&amp;gt;typeFlags: 0&amp;lt;/code&amp;gt; when you want integers to be interpreted as unsigned, or &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; to include negative values. When «bytesPer» is 8, integers are read in as signed regardless.&lt;br /&gt;
&lt;br /&gt;
A standard Intel convention writes numbers (integers or floating point values) with the least significant bytes written first, least significant bytes last, which is termed &amp;quot;little-endian format&amp;quot;. This is the default assumed by [[WriteBinaryFile]] unless the &amp;lt;code&amp;gt;typeFlags = 32&amp;lt;/code&amp;gt; flag is specified. &amp;quot;Big endian&amp;quot; means that the most significant byte is written first.&lt;br /&gt;
&lt;br /&gt;
You can add the &amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt; &amp;quot;big endian&amp;quot; option to the data type selection. So, for example, a value of &amp;lt;code&amp;gt;2 + 32&amp;lt;/code&amp;gt; would specify a floating point format (&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;) with the byte order reversed (&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The Value type is a variant data type, in which a leading byte encodes the internal data type of the value, and followed by an 8-byte value. The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; only writes Analytica data types that can be fully encoded in with 8 bytes, which includes integers, fixed-point reals, floating point reals, date and date-time numbers, and the special value [[Null]]. When using this type, [[Null]] values ARE written to the file.  The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; cannot be used to write text values, since these vary in length. The cells will each use 9 bytes, and will be spaced every 9 bytes in the file.&lt;br /&gt;
&lt;br /&gt;
The «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; extends option &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; by allowing text values{{Release|6.2|| or binary data}}. When a text value occurs, the first byte indicates that the value is text, the next four bytes encode the length, &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt;, and the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; bytes encodes the characters in UTF-8. {{Release|6.2||When a binary data &amp;quot;blob&amp;quot; occurs, the first byte indicates the value in binary, the next 8 bytes specify the number of bytes, and then the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; bytes are the data.}} When this format is used, the «bytesPer» parameter must be omitted. The location of items in the file are not spaced at any predictable interval, since text items vary in length.&lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||The «typeFlags» option of 7 reads the next «bytesPer» bytes of the file into memory as a binary data term. When «bytesPer» is INF or omitted, the entire file is read.  When «bytesPer» is specified and you haven't specified an index, it'll read a list of binary data terms of the given size. If you have specified and index, it'll read up to the index length binary data chunks.  You can use this to read a binary file into memory, and then use [[GetFromBinaryData]] to perform multiple reads at different locations.  This avoids extra overhead of opening and closing the file during each read.  [[GetFromBinaryData]] has the same parameters as ReadBinaryFile, but reads from an in-memory binary term rather than from a binary file on disk.}}&lt;br /&gt;
&lt;br /&gt;
==== offset ====&lt;br /&gt;
Specifies the file position to start reading from. Negative value specifies the distance (in bytes) from the end of the file, and a positive or zero value specifies the distance in bytes from the start of the file. You can use «offset» parameter to read data from a particular location inside the file. &lt;br /&gt;
&lt;br /&gt;
When «offset» varies with the result index(es), you can use [[Null]] values in the «offset» array to indicate that the item resides directly after the previously read item. Hence, set to non-null integer values only for those items that start at a new offset.&lt;br /&gt;
&lt;br /&gt;
It is likely you'll want to limit the number if items read to a maximum number. To do this, specify a result index. The length of the result index will be used as the maximum number of items read.&lt;br /&gt;
&lt;br /&gt;
==== showDialog ====&lt;br /&gt;
This is a flag to force or suppress the file selector dialog. When not specified, the dialog only displays if needed, for example, if the file name is blank or the file doesn't exist. Setting «showDialog» to false suppresses the dialog from appearing. Setting «showDialog» to true forces the dialog to display, using «filename» as the initial default.&lt;br /&gt;
&lt;br /&gt;
==== title ====&lt;br /&gt;
The text to use as caption of file selector dialog.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
==== extensionFilter ====&lt;br /&gt;
(''New in [[Analytica 7.1]]'') Overrides the file types offered in the file-selector dialog. Specify the filter(s) as a text in any of these forms:&lt;br /&gt;
* ''Display form'' &amp;amp;mdash; one or more filters separated by semicolons, each a description with its patterns in parentheses, e.g. &amp;lt;code&amp;gt;&amp;quot;Data Files (*.dat, *.bin); All Files (*.*)&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''A list of'' &amp;lt;code&amp;gt;&amp;quot;Description{{!}}patterns&amp;quot;&amp;lt;/code&amp;gt; ''filters'' (description first, patterns separated by &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;), e.g. &amp;lt;code&amp;gt;[&amp;quot;Data files{{!}}*.dat;*.bin&amp;quot;, &amp;quot;All files{{!}}*.*&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Just patterns'', e.g. &amp;lt;code&amp;gt;&amp;quot;*.dat;*.bin&amp;quot;&amp;lt;/code&amp;gt; (a description is generated automatically).&lt;br /&gt;
An &amp;lt;code&amp;gt;&amp;quot;All files (*.*)&amp;quot;&amp;lt;/code&amp;gt; entry is appended automatically unless your list already includes one. When omitted, the default file types are shown.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Fast Writing and reading of Analytica arrays ===&lt;br /&gt;
&lt;br /&gt;
[[WriteBinaryFile]]() and [[ReadBinaryFile]]() are the fastest ways to write data from a model to a file or read from a file, because the numeric data does not need to be converted to text when writing or parsed when reading. &lt;br /&gt;
&lt;br /&gt;
Assume: &amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt; is an array indexed by indexes &amp;lt;code&amp;gt;I, J, K&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;. Assume also that it contains only numbers, dates and null values -- no text, [[handles]], [[references]], etc.&lt;br /&gt;
&lt;br /&gt;
Write the array to the file:&lt;br /&gt;
: &amp;lt;code&amp;gt;[[WriteBinaryFile]](&amp;quot;a.dat&amp;quot;, a, I,J,K,L, bytesPer:12, typeFlags:3 )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Read the array back in:&lt;br /&gt;
:&amp;lt;code&amp;gt;[[ReadBinaryFile]](&amp;quot;a.dat&amp;quot;, bytesPer:12, typeFlags:3, resultIndex: I, J, K, L )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reading a complex binary structure ===&lt;br /&gt;
&lt;br /&gt;
Binary Shape files (*.shp) and Shape index files (*.shx) have the following header layout for their first 100 bytes:&lt;br /&gt;
::[[image:SHP_file_header_layout.png]]&lt;br /&gt;
&lt;br /&gt;
To read this, create an index for the items of the header:&lt;br /&gt;
:Index Header_item := &amp;lt;code&amp;gt;['File Code','Unused','Unused','Unused','Unused','Unused','File length','Version','Shape type','Xmin','Ymin','Xmax','Ymax','Zmin','Zmax','Mmin','Mmax']&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The bytes per item varies:&lt;br /&gt;
:Variable BytesPerItem := &amp;lt;code&amp;gt;Table(Header_item)(4,4,4,4,4,4,4,4,4,8,8,8,8,8,8,8,8)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A big-endian (positive) integer is «typeFlag» 32, a little-endian integer is 0, and a little-endian double is 2. So the item types are:&lt;br /&gt;
:Variable ItemType := &amp;lt;code&amp;gt;Table(Header_item)(32,32,32,32,32,32,32,0,0,2,2,2,2,2,2,2,2)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full header is then read using:&lt;br /&gt;
:&amp;lt;code&amp;gt;[[ReadBinaryFile]](&amp;quot;filename.shx&amp;quot;, bytesPer: BytesPerItem, typeFlags:itemType, resultIndex: Header_item )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following model embellishes this with a user-interface for selecting the items in a general binary data record and using this to read the structure. For complex binary structures, this may simplify the coding.&lt;br /&gt;
::[[image:shx_read_binary_UI.png]]&lt;br /&gt;
* '''Model file: ''' [[media:Reading binary data file.ana|Reading binary data file.ana]]&lt;br /&gt;
* '''Try the model with this binary data file: ''' [[file:NHDWaterbody.shx|NHDWaterbody.shx]]&lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||&lt;br /&gt;
== From ACP ==&lt;br /&gt;
By specifying a blank filename, or a filename that you know does not exist on the server, ACP will display a file selector dialog on the user's browser, asking her to select a file for upload. &lt;br /&gt;
&lt;br /&gt;
This can be utilized to upload an arbitrary file type to disk, since you can use this to upload the file into memory (by setting «typeFlags» to 7), and then using WriteBinaryFile to save it to the server's disk (again, setting «typeFlags» to 7).   This trick can be utilized to upload a spreadsheet when using [[LibXL]] for reading spreadsheet data where Excel is not installed on the server, as is the case on Lumina's public ACP server.  For security reasons, Excel is not installed on Lumina's public ACP server.}}&lt;br /&gt;
&lt;br /&gt;
== From ADE ==&lt;br /&gt;
When evaluated in the [[ADE|Analytica Decision Engine (ADE)]] and a dialog needs to be shown to the end-user, it calls [[IAdeUICallbacks::GetFilename]](...). From within that callback, the parent application can interact with the end-user to resolve the file path, and a web applications can instruct the end-user to upload a file. Once complete, the callback returns the full path to the file which is then read. To receive this callback, the parent application must have previously registered the callback with ADE using [[CAEngine::SetCallbackObject]]( ). &lt;br /&gt;
&lt;br /&gt;
Once the file read completes, it calls [[IAdeUICallbacks::FileOpenCompleted]]().&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:2;-moz-column-count:2;-webkit-column-count:2&amp;quot;&amp;gt;&lt;br /&gt;
* [[In-memory binary data terms]]&lt;br /&gt;
* [[Binary and hexadecimal integer formats]]&lt;br /&gt;
* [[ReadTextFile]]&lt;br /&gt;
* [[WriteBinaryFile]]&lt;br /&gt;
* [[GetFromBinaryData]]&lt;br /&gt;
* [[Dec2Bin]]&lt;br /&gt;
* [[Hex2Bin]]&lt;br /&gt;
* [[Bin2Dec]]&lt;br /&gt;
* [[Bin2Hex]]&lt;br /&gt;
* [[BitAnd]]&lt;br /&gt;
* [[BitOr]]&lt;br /&gt;
* [[BitXOr]]&lt;br /&gt;
* [[BitNot]]&lt;br /&gt;
* [[BitShift]] -- these can be useful when you need to manipulate the bytes of multi-byte integers that you read.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=ReadBinaryFile&amp;diff=64035</id>
		<title>ReadBinaryFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=ReadBinaryFile&amp;diff=64035"/>
		<updated>2026-06-29T19:48:27Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Add extensionFilter to signature (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Database Functions]]&lt;br /&gt;
[[category:System Functions]]&lt;br /&gt;
[[category:File system functions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
''Requires [[Analytica 5.0]] {{Developer}} or higher''&lt;br /&gt;
&lt;br /&gt;
== ReadBinaryFile(filename'', bytesPer, typeFlags, offset, resultIndex..., showDialog, title{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Reads data directly from a binary (i.e., non-text) file.&lt;br /&gt;
&lt;br /&gt;
Flat data files are usually read using [[ReadTextFile]]. When you read text files, end-of-line characters are interpreted in various ways for you, conversions from character sets such as UTF-8 or Unicode may occur, and certain special byte values such as the zero byte or end-of-file cannot occur in the file. In contrast, reading from a binary file gives you access to the bytes of the file exactly as they appear.&lt;br /&gt;
&lt;br /&gt;
[[ReadBinaryFile]] is most commonly used when you have a data file in a binary data format from another application, and need to access the internal bytes at particular locations. It can also be used in conjunction with [[WriteBinaryFile]] as a fast and convenient method to dump an Analytica array to a file and load it back in later.&lt;br /&gt;
&lt;br /&gt;
The function [[GetFromBinaryData]] operates identically to [[ReadBinaryFile]], except that it reads from an in-memory binary data term rather than from a file. If you plan to run your model runs in ACP over the web, it is important to read the file into memory with one call, and then use [[GetFromBinaryData]] to read each item so that the user is asked to upload the file only once.&lt;br /&gt;
&lt;br /&gt;
== Result Value(s) ==&lt;br /&gt;
These values are returned:&lt;br /&gt;
# The contents read. &lt;br /&gt;
# The full file path&lt;br /&gt;
# The offset where it left off reading. Useful if you want to read a different data structure that starts afterwards. (new to [[Analytica 6.4]]).&lt;br /&gt;
&lt;br /&gt;
The main result returned is the contents it reads. This will either be an array indexed by the index(es) you specify in the «resultIndex» parameter, or a list of items if you omit the «resultIndex» parameter.&lt;br /&gt;
&lt;br /&gt;
To capture one or both of the other result values, use:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] ( content, path, nextOffset ) := [[ReadBinaryFile]](....)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Reading bytes ==&lt;br /&gt;
The usage&lt;br /&gt;
:&amp;lt;code&amp;gt;ReadBinaryFile(filename)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
returns the contents of the file as bytes, a list of integer values between 0 and 255.&lt;br /&gt;
&lt;br /&gt;
== Reading N values ==&lt;br /&gt;
To limit the number of items read, pass an index to the «resultIndex» parameter having a length equal to the maximum number of items to read. The actual number read will be less if the end-of-file is reached.  For example,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;ReadBinaryFile(filename, resultIndex: I)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parameters ==&lt;br /&gt;
==== filename ==== &lt;br /&gt;
Name of file to read from.&lt;br /&gt;
&lt;br /&gt;
File name paths can be either relative or absolute. An absolute path specifies the full path of the file from a root drive, such as &lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;C:\Users\Drice\Documents\Projects\FatigueAnalysis\Results.bin&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A relative filename incompletely specifies a file path, and is interpreted relative to the [[CurrentDataDirectory]]. &lt;br /&gt;
&lt;br /&gt;
====  I... ====&lt;br /&gt;
&lt;br /&gt;
The index(es) that you want as index(es) of the result. If you provide no index, it returns an unindexed list, so the variable calling ReadBinaryFile will appear as the index. If you provide multiple indexes, the last index listed vary fastest and first varies slowest as items are read.  &lt;br /&gt;
&lt;br /&gt;
The number of bytes to read depends on the product of the sizes of the indexes and the number of bytes per cell, which could vary if Bytesper parameter varies by one or more of the Indexes.  If the total is less than the number of bytes in the file, it will read only the amount of data needed. If the total is more than the file size, it will pad out the excess cells with NULL. &lt;br /&gt;
&lt;br /&gt;
If the indexes are in a different order in the file from the canonical order within Analytica, it reforms (transposes) the array to the internal form needed. If the amount of data is very large file (e.g. file has hundreds of MB), this reform process can be quite time-consuming.&lt;br /&gt;
&lt;br /&gt;
==== bytesPer ====&lt;br /&gt;
Specifies the number of bytes per item read. For example, when you specify &amp;lt;code&amp;gt;bytesPer: 4&amp;lt;/code&amp;gt;, then each 4 bytes becomes one cell of the result. When this is 1, then each byte is read and returned as a separate cell. Using 8 for «bytesPer» will result in the most memory-efficient encoding of contents when it is read into memory, since there is 8 times as much information per cell as would be the case for single bytes (and the bytes required per cell in memory would be the same in both cases). &lt;br /&gt;
&lt;br /&gt;
When reading integer values (as is the default when «typeFlags» is omitted), this specifies the number of bytes per integer word, and can be 1 (for single bytes), 2 (for 16-bit words), 4 (for 32-bit integers) or 8 (for 64-bit integers).&lt;br /&gt;
&lt;br /&gt;
When reading floating point real numbers, «bytesPer» can be 4 (for 32-bit IEEE 754 reals, often called '''''float'''''s), or 8 (for 64-bit IEEE 754 reals, often called '''''double'''''s). When «typeFlags» has &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; (floating point), the default for «bytesPer» is 8 if not specified.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;, nine bytes per item are used, so you can either omit «bytesPer» or set it to 9. Any other value throws an error.&lt;br /&gt;
&lt;br /&gt;
For the «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;, the number of bytes per item may vary (depending on the length of text values), and so «bytesPer» must be omitted or an error will be issued.&lt;br /&gt;
&lt;br /&gt;
==== typeFlags ====&lt;br /&gt;
Controls how each item read gets converted into a value.&lt;br /&gt;
:&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; = Unsigned integer (positive only)&lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; = Signed integer (positive and negative numbers)&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; = IEEE 754 Floating point real&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; = Value (numbers, dates and null). 9 bytes per item.&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; = Value (including text{{Release|6.2|| or binary data}}). Variable bytes per text item.{{Release|6.2||&lt;br /&gt;
:&amp;lt;code&amp;gt;7&amp;lt;/code&amp;gt; {{=}} Raw binary data.&lt;br /&gt;
:&amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; {{=}} image}}&lt;br /&gt;
:&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt; = Big endian flag. &lt;br /&gt;
&lt;br /&gt;
You can say the one-byte integer with hex value 0xc1 is equal to 193, or you can say that it equals -133.  The distinction here is whether you interpret the raw binary data as representing an unsigned integer (193) or a signed integer (-133). Signed integers use two's-complement so that both negative and positive values are within the possible range. Use &amp;lt;code&amp;gt;typeFlags: 0&amp;lt;/code&amp;gt; when you want integers to be interpreted as unsigned, or &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; to include negative values. When «bytesPer» is 8, integers are read in as signed regardless.&lt;br /&gt;
&lt;br /&gt;
A standard Intel convention writes numbers (integers or floating point values) with the least significant bytes written first, least significant bytes last, which is termed &amp;quot;little-endian format&amp;quot;. This is the default assumed by [[WriteBinaryFile]] unless the &amp;lt;code&amp;gt;typeFlags = 32&amp;lt;/code&amp;gt; flag is specified. &amp;quot;Big endian&amp;quot; means that the most significant byte is written first.&lt;br /&gt;
&lt;br /&gt;
You can add the &amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt; &amp;quot;big endian&amp;quot; option to the data type selection. So, for example, a value of &amp;lt;code&amp;gt;2 + 32&amp;lt;/code&amp;gt; would specify a floating point format (&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;) with the byte order reversed (&amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The Value type is a variant data type, in which a leading byte encodes the internal data type of the value, and followed by an 8-byte value. The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; only writes Analytica data types that can be fully encoded in with 8 bytes, which includes integers, fixed-point reals, floating point reals, date and date-time numbers, and the special value [[Null]]. When using this type, [[Null]] values ARE written to the file.  The «typeFlags» option of &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; cannot be used to write text values, since these vary in length. The cells will each use 9 bytes, and will be spaced every 9 bytes in the file.&lt;br /&gt;
&lt;br /&gt;
The «typeFlags» option of &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; extends option &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; by allowing text values{{Release|6.2|| or binary data}}. When a text value occurs, the first byte indicates that the value is text, the next four bytes encode the length, &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt;, and the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; bytes encodes the characters in UTF-8. {{Release|6.2||When a binary data &amp;quot;blob&amp;quot; occurs, the first byte indicates the value in binary, the next 8 bytes specify the number of bytes, and then the next &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; bytes are the data.}} When this format is used, the «bytesPer» parameter must be omitted. The location of items in the file are not spaced at any predictable interval, since text items vary in length.&lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||The «typeFlags» option of 7 reads the next «bytesPer» bytes of the file into memory as a binary data term. When «bytesPer» is INF or omitted, the entire file is read.  When «bytesPer» is specified and you haven't specified an index, it'll read a list of binary data terms of the given size. If you have specified and index, it'll read up to the index length binary data chunks.  You can use this to read a binary file into memory, and then use [[GetFromBinaryData]] to perform multiple reads at different locations.  This avoids extra overhead of opening and closing the file during each read.  [[GetFromBinaryData]] has the same parameters as ReadBinaryFile, but reads from an in-memory binary term rather than from a binary file on disk.}}&lt;br /&gt;
&lt;br /&gt;
==== offset ====&lt;br /&gt;
Specifies the file position to start reading from. Negative value specifies the distance (in bytes) from the end of the file, and a positive or zero value specifies the distance in bytes from the start of the file. You can use «offset» parameter to read data from a particular location inside the file. &lt;br /&gt;
&lt;br /&gt;
When «offset» varies with the result index(es), you can use [[Null]] values in the «offset» array to indicate that the item resides directly after the previously read item. Hence, set to non-null integer values only for those items that start at a new offset.&lt;br /&gt;
&lt;br /&gt;
It is likely you'll want to limit the number if items read to a maximum number. To do this, specify a result index. The length of the result index will be used as the maximum number of items read.&lt;br /&gt;
&lt;br /&gt;
==== showDialog ====&lt;br /&gt;
This is a flag to force or suppress the file selector dialog. When not specified, the dialog only displays if needed, for example, if the file name is blank or the file doesn't exist. Setting «showDialog» to false suppresses the dialog from appearing. Setting «showDialog» to true forces the dialog to display, using «filename» as the initial default.&lt;br /&gt;
&lt;br /&gt;
==== title ====&lt;br /&gt;
The text to use as caption of file selector dialog.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Fast Writing and reading of Analytica arrays ===&lt;br /&gt;
&lt;br /&gt;
[[WriteBinaryFile]]() and [[ReadBinaryFile]]() are the fastest ways to write data from a model to a file or read from a file, because the numeric data does not need to be converted to text when writing or parsed when reading. &lt;br /&gt;
&lt;br /&gt;
Assume: &amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt; is an array indexed by indexes &amp;lt;code&amp;gt;I, J, K&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;l&amp;lt;/code&amp;gt;. Assume also that it contains only numbers, dates and null values -- no text, [[handles]], [[references]], etc.&lt;br /&gt;
&lt;br /&gt;
Write the array to the file:&lt;br /&gt;
: &amp;lt;code&amp;gt;[[WriteBinaryFile]](&amp;quot;a.dat&amp;quot;, a, I,J,K,L, bytesPer:12, typeFlags:3 )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Read the array back in:&lt;br /&gt;
:&amp;lt;code&amp;gt;[[ReadBinaryFile]](&amp;quot;a.dat&amp;quot;, bytesPer:12, typeFlags:3, resultIndex: I, J, K, L )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reading a complex binary structure ===&lt;br /&gt;
&lt;br /&gt;
Binary Shape files (*.shp) and Shape index files (*.shx) have the following header layout for their first 100 bytes:&lt;br /&gt;
::[[image:SHP_file_header_layout.png]]&lt;br /&gt;
&lt;br /&gt;
To read this, create an index for the items of the header:&lt;br /&gt;
:Index Header_item := &amp;lt;code&amp;gt;['File Code','Unused','Unused','Unused','Unused','Unused','File length','Version','Shape type','Xmin','Ymin','Xmax','Ymax','Zmin','Zmax','Mmin','Mmax']&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The bytes per item varies:&lt;br /&gt;
:Variable BytesPerItem := &amp;lt;code&amp;gt;Table(Header_item)(4,4,4,4,4,4,4,4,4,8,8,8,8,8,8,8,8)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A big-endian (positive) integer is «typeFlag» 32, a little-endian integer is 0, and a little-endian double is 2. So the item types are:&lt;br /&gt;
:Variable ItemType := &amp;lt;code&amp;gt;Table(Header_item)(32,32,32,32,32,32,32,0,0,2,2,2,2,2,2,2,2)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full header is then read using:&lt;br /&gt;
:&amp;lt;code&amp;gt;[[ReadBinaryFile]](&amp;quot;filename.shx&amp;quot;, bytesPer: BytesPerItem, typeFlags:itemType, resultIndex: Header_item )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following model embellishes this with a user-interface for selecting the items in a general binary data record and using this to read the structure. For complex binary structures, this may simplify the coding.&lt;br /&gt;
::[[image:shx_read_binary_UI.png]]&lt;br /&gt;
* '''Model file: ''' [[media:Reading binary data file.ana|Reading binary data file.ana]]&lt;br /&gt;
* '''Try the model with this binary data file: ''' [[file:NHDWaterbody.shx|NHDWaterbody.shx]]&lt;br /&gt;
&lt;br /&gt;
{{Release|6.2||&lt;br /&gt;
== From ACP ==&lt;br /&gt;
By specifying a blank filename, or a filename that you know does not exist on the server, ACP will display a file selector dialog on the user's browser, asking her to select a file for upload. &lt;br /&gt;
&lt;br /&gt;
This can be utilized to upload an arbitrary file type to disk, since you can use this to upload the file into memory (by setting «typeFlags» to 7), and then using WriteBinaryFile to save it to the server's disk (again, setting «typeFlags» to 7).   This trick can be utilized to upload a spreadsheet when using [[LibXL]] for reading spreadsheet data where Excel is not installed on the server, as is the case on Lumina's public ACP server.  For security reasons, Excel is not installed on Lumina's public ACP server.}}&lt;br /&gt;
&lt;br /&gt;
== From ADE ==&lt;br /&gt;
When evaluated in the [[ADE|Analytica Decision Engine (ADE)]] and a dialog needs to be shown to the end-user, it calls [[IAdeUICallbacks::GetFilename]](...). From within that callback, the parent application can interact with the end-user to resolve the file path, and a web applications can instruct the end-user to upload a file. Once complete, the callback returns the full path to the file which is then read. To receive this callback, the parent application must have previously registered the callback with ADE using [[CAEngine::SetCallbackObject]]( ). &lt;br /&gt;
&lt;br /&gt;
Once the file read completes, it calls [[IAdeUICallbacks::FileOpenCompleted]]().&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:2;-moz-column-count:2;-webkit-column-count:2&amp;quot;&amp;gt;&lt;br /&gt;
* [[In-memory binary data terms]]&lt;br /&gt;
* [[Binary and hexadecimal integer formats]]&lt;br /&gt;
* [[ReadTextFile]]&lt;br /&gt;
* [[WriteBinaryFile]]&lt;br /&gt;
* [[GetFromBinaryData]]&lt;br /&gt;
* [[Dec2Bin]]&lt;br /&gt;
* [[Hex2Bin]]&lt;br /&gt;
* [[Bin2Dec]]&lt;br /&gt;
* [[Bin2Hex]]&lt;br /&gt;
* [[BitAnd]]&lt;br /&gt;
* [[BitOr]]&lt;br /&gt;
* [[BitXOr]]&lt;br /&gt;
* [[BitNot]]&lt;br /&gt;
* [[BitShift]] -- these can be useful when you need to manipulate the bytes of multi-byte integers that you read.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=ReadTextFile&amp;diff=64034</id>
		<title>ReadTextFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=ReadTextFile&amp;diff=64034"/>
		<updated>2026-06-29T19:44:37Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document extensionFilter parameter (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:System Functions]]&lt;br /&gt;
[[category:Database Functions]]&lt;br /&gt;
[[category:File system functions]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
''(Requires Analytica {{Developer}}, Optimizer, or Power Player)''&lt;br /&gt;
&lt;br /&gt;
== ReadTextFile(filename, ''showDialog, title{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Returns the contents a text file «filename» as a text value. «filename» may be the name of a file in the [[CurrentDataDirectory|Current Data Directory]] (initially, the directory containing the model), or a path relative to the [[CurrentDataDirectory|Current Data Directory]] , or an absolute pathname.&lt;br /&gt;
&lt;br /&gt;
If it can't find a file with that name, by default, it opens a file browser dialog to let the user select another file. Set optional parameter, «showDialog» to &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; (1) to show the file browser dialog, using «filename» as default, even if the file exists. Set «showDialog» to &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt; (0) to never show it. If it can't find the file, it shows an error message.&lt;br /&gt;
&lt;br /&gt;
You can specify the caption for the title bar of the file browser dialog titlebar in the optional «title» parameter.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
«extensionFilter»: (Optional) Overrides the file types offered in the file-selector dialog. Specify the filter(s) as a text in any of these forms:&lt;br /&gt;
* ''Display form'' &amp;amp;mdash; one or more filters separated by semicolons, each a description with its patterns in parentheses, e.g. &amp;lt;code&amp;gt;&amp;quot;Text Files (*.txt); CSV Files (*.csv); All Files (*.*)&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''A list of'' &amp;lt;code&amp;gt;&amp;quot;Description{{!}}patterns&amp;quot;&amp;lt;/code&amp;gt; ''filters'' (description first, patterns separated by &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;), e.g. &amp;lt;code&amp;gt;[&amp;quot;Text files{{!}}*.txt;*.csv&amp;quot;, &amp;quot;All files{{!}}*.*&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Just patterns'', e.g. &amp;lt;code&amp;gt;&amp;quot;*.txt;*.csv&amp;quot;&amp;lt;/code&amp;gt; (a description is generated automatically).&lt;br /&gt;
An &amp;lt;code&amp;gt;&amp;quot;All files (*.*)&amp;quot;&amp;lt;/code&amp;gt; entry is appended automatically unless your list already includes one. When omitted, the default file types are shown.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[ADE]] never shows the file browser dialog, no matter what the parameter values.&lt;br /&gt;
&lt;br /&gt;
== Treating End-of-line ==&lt;br /&gt;
There are three common standards in text-files to identify newlines:&lt;br /&gt;
* Windows files usually use the two-character sequence CRLF -- [[Chr]](10) [[Chr]](13)&lt;br /&gt;
* Unix files use a single LF character -- [[Chr]](10)&lt;br /&gt;
* Macintosh OS files use a single CR character -- [[Chr]](13)&lt;br /&gt;
&lt;br /&gt;
Occasional Windows-based programs use one of the other standards.&lt;br /&gt;
&lt;br /&gt;
ReadTextFile insulates you from worrying about which standard is used by converting each to the Unix standard, a single LF -- [[Chr]](10).&lt;br /&gt;
&lt;br /&gt;
If a file contains inconsistent line breaks -- e.g. including more than one examples of LF, CRLF, and CR -- it converts LF and CRLF to a single LF, and leaves CR -- Chr(13) -- as is.&lt;br /&gt;
&lt;br /&gt;
== Getting the file name actually opened ==&lt;br /&gt;
Your code may want to know the file path for which file was actually opened. This may differ from «filename» when the specified file is not found, or when «showDialog» forces a dialog, allowing the user to select a different file. [[ReadTextFile]] returns the file path as a second return value, which you can optionally capture using, e.g.,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] (contents, filepath) := [[ReadTextFile]]( ... );&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A common pattern is that you may want to save the filename in a variable such that when the evaluation is repeated in the future, it can supply the file selected by the user to the «filename» parameter. This can be coded by supplying first a global variable to hold the filename defined using [[ComputedBy]] with the default filename as follows:&lt;br /&gt;
&lt;br /&gt;
:Variable TheFilename ::=&lt;br /&gt;
::&amp;lt;code&amp;gt;[[ComputedBy]]( TheFileContetns, &amp;quot;defaultFilename&amp;quot; ) &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Variable TheFileContents ::=&lt;br /&gt;
::&amp;lt;code&amp;gt;( , TheFilename ) := [[ReadTextFile]]( TheFilename )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The assignment to &amp;lt;code&amp;gt;( , TheFilename )&amp;lt;/code&amp;gt; passes through the first parameter as the result of the assignment expression, but assigns the second return value the &amp;lt;code&amp;gt;TheFilename&amp;lt;/code&amp;gt;. The assignment to &amp;lt;code&amp;gt;TheFilename&amp;lt;/code&amp;gt; is a [[side-effect]] that is allowed only because &amp;lt;code&amp;gt;TheFilename&amp;lt;/code&amp;gt; is defined as a [[ComputedBy]]. The assignment changes the value, but also rewrites the second parameter of the call to [[ComputedBy]], thus permanently preserving the filename selected. The one line definition of &amp;lt;code&amp;gt;TheFileContents&amp;lt;/code&amp;gt; is locally equivalent to:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] (contents, filename ) := [[ReadTextFile]]( TheFilename );&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;TheFilename := filename;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;contents&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Release|1=6.6|2=|3=&lt;br /&gt;
== Getting the file encoding ==&lt;br /&gt;
(''New in [[Analytica 6.6]]'')&lt;br /&gt;
A text file may include a Byte Mark Encoding (BOM) as the first few characters of the file. This can be captured as the fourth return value and will have one the the values:&lt;br /&gt;
* [[Null]] : No BOM. Presumed to be ASCII.&lt;br /&gt;
* &amp;lt;code&amp;gt;'UTF-8'&amp;lt;/code&amp;gt;: Each character uses a variable number of bytes, from 1-6 depending on the character.&lt;br /&gt;
* &amp;lt;code&amp;gt;'UTF-16be'&amp;lt;/code&amp;gt;: 2 bytes per character, big-endian.&lt;br /&gt;
* &amp;lt;code&amp;gt;'UTF-16le'&amp;lt;/code&amp;gt;: 2 bytes per character, little-endian&lt;br /&gt;
&lt;br /&gt;
Example of capturing the encoding:&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] ( contents, filepath, isUploaded, encoding ) := [[ReadTextFile]]( filename );&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
== From ADE ==&lt;br /&gt;
When evaluated in [[ADE|the Analytica Decision Engine (ADE)]] and a dialog needs to be shown to the end-user, it calls [[IAdeUICallbacks::GetFilename]](...). From within that callback, the parent application can interact with the end-user to resolve the file path, and a web applications can instruct the end-user to upload a file. Once complete, the callback returns the full path to the file which is then read. To receive this callback, the parent application must have previously registered the callback with ADE using [[CAEngine::SetCallbackObject]]( ). If it has not registered a callback and the file doesn't exist, returns an empty text.&lt;br /&gt;
&lt;br /&gt;
Once the file read completes, it calls [[IAdeUICallbacks::FileOpenCompleted]]().&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
* The «title» parameter was introduced in [[Analytica 4.6]].&lt;br /&gt;
&lt;br /&gt;
* The callback in ADE was introduced in [[Analytica 4.6|ADE 4.6]].&lt;br /&gt;
&lt;br /&gt;
* The «extensionFilter» parameter was introduced in [[Analytica 7.1]].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[WriteTextFile]]&lt;br /&gt;
* [[Read and write text files]]&lt;br /&gt;
* [[Text functions]]&lt;br /&gt;
* [[ParseCSV]]&lt;br /&gt;
* [[ParseJSON]]&lt;br /&gt;
* [[ReadFromUrl]]&lt;br /&gt;
* [[ReadImageFile]]&lt;br /&gt;
* [[ReadExportFile]]&lt;br /&gt;
* [[ReadBinaryFile]]&lt;br /&gt;
* [[Model File Character Encoding]]&lt;br /&gt;
* [[Chr]]&lt;br /&gt;
* [[CurrentDataFolder]]&lt;br /&gt;
* [[NumberToText]]&lt;br /&gt;
* [[Files and Editing]]&lt;br /&gt;
* [[Returning multiple values]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=WriteTextFile&amp;diff=64033</id>
		<title>WriteTextFile</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=WriteTextFile&amp;diff=64033"/>
		<updated>2026-06-29T19:35:52Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document extensionFilter parameter (new in 7.1, ER 20237)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:System Functions]]&lt;br /&gt;
[[category:Database Functions]]&lt;br /&gt;
[[category:File system functions]]&lt;br /&gt;
[[Category:Doc Status D]] &amp;lt;!-- For Lumina use, do not change --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
== WriteTextFile(filename, text'', append, warn, sep, showDialog, encoding{{Release|6.0||, download}}{{Release|7.1||, extensionFilter}}'') ==&lt;br /&gt;
&lt;br /&gt;
Write «text» value to a file with name «filename».&lt;br /&gt;
&lt;br /&gt;
=== Optional parameters ===&lt;br /&gt;
&lt;br /&gt;
«append»: Default &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;. If the file exists and «append» is &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;, it appends the text to the end of the file. If it doesn't exist and «warn» is &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; , it asks whether to create the file.&lt;br /&gt;
&lt;br /&gt;
«warn»: Default &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;. If «warn» is &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;, it suppresses the warning that the file already exists when «append» is false or that it does not exist when «append» is True.&lt;br /&gt;
&lt;br /&gt;
«showDialog»: Default &amp;lt;code&amp;gt;Undefined&amp;lt;/code&amp;gt; -- i.e. it shows a file browser dialog only if the indicated filename is a folder, a read-only file, or if it exists and «warn» is &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;, or if it does not exist and «append» is &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;. When «showDialog» is &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;, it always opens a dialog before with file name as the default to let the user change file name or folder. When &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;, it never shows a dialog but may generate an error when trying to overwrite an existing file with «append» False.&lt;br /&gt;
&lt;br /&gt;
«sep»: (Default is a new line.) Character to use as a separator between elements when «text» is an array.&lt;br /&gt;
&lt;br /&gt;
«encoding» (Default &amp;lt;code&amp;gt;&amp;quot;ANSI&amp;quot;&amp;lt;/code&amp;gt;.) Specifies how to encode characters in the file:&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;ANSI&amp;quot;&amp;lt;/code&amp;gt; : One byte per character, [http://en.wikipedia.org/wiki/8859 ISO-8859-1]. Extended characters (above ascii 255) are written as ?.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;UTF-8&amp;quot;&amp;lt;/code&amp;gt; : [http://en.wikipedia.org/wiki/UTF-8 UTF-8 encoding] with a [http://en.wikipedia.org/wiki/Byte_order_mark byte order mark] ([http://en.wikipedia.org/wiki/Byte_order_mark BOM]). The UTF-8 encoding uses one byte for comman characters, and 2-3 bytes for characters with ascii values above 127.&lt;br /&gt;
*&amp;lt;code&amp;gt; &amp;quot;-UTF-8&amp;quot;&amp;lt;/code&amp;gt; : [http://en.wikipedia.org/wiki/UTF-8 UTF-8 encoding] without a BOM.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;UTF-16&amp;quot;&amp;lt;/code&amp;gt; : Two bytes per character, big endian, with BOM.&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;quot;UTF-16le&amp;quot;&amp;lt;/code&amp;gt; : Two bytes per character, little endian, with BOM.&lt;br /&gt;
&lt;br /&gt;
{{Release|6.0||&lt;br /&gt;
«download»: This is only used when running the model in [[ACP]]. When set to &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;, the «text» is downloaded onto the end-user's computer as a text file with the given «filename». }}&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
«extensionFilter»: (Optional) Overrides the file types offered in the file-selector dialog. Specify the filter(s) as a text in any of these forms:&lt;br /&gt;
* ''Display form'' &amp;amp;mdash; one or more filters separated by semicolons, each a description with its patterns in parentheses, e.g. &amp;lt;code&amp;gt;&amp;quot;Text Files (*.txt); CSV Files (*.csv); All Files (*.*)&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''A list of'' &amp;lt;code&amp;gt;&amp;quot;Description{{!}}patterns&amp;quot;&amp;lt;/code&amp;gt; ''filters'' (description first, patterns separated by &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;), e.g. &amp;lt;code&amp;gt;[&amp;quot;Text files{{!}}*.txt;*.csv&amp;quot;, &amp;quot;All files{{!}}*.*&amp;quot;]&amp;lt;/code&amp;gt;.&lt;br /&gt;
* ''Just patterns'', e.g. &amp;lt;code&amp;gt;&amp;quot;*.txt;*.csv&amp;quot;&amp;lt;/code&amp;gt; (a description is generated automatically).&lt;br /&gt;
An &amp;lt;code&amp;gt;&amp;quot;All files (*.*)&amp;quot;&amp;lt;/code&amp;gt; entry is appended automatically unless your list already includes one. When omitted, the default file types are shown.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==History==&lt;br /&gt;
Introduced in [[What's new in Analytica 4.0?|Analytica 4.0]].&lt;br /&gt;
&lt;br /&gt;
«encoding» parameter introduced in [[Analytica 4.5]].&lt;br /&gt;
&lt;br /&gt;
«download» parameter introduced in [[Analytica 6.0]].&lt;br /&gt;
&lt;br /&gt;
«extensionFilter» parameter introduced in [[Analytica 7.1]].&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[ReadTextFile]]&lt;br /&gt;
* [[Read and write text files]]&lt;br /&gt;
* [[MakeCSV]]&lt;br /&gt;
* [[MakeJSON]]&lt;br /&gt;
* [[Text functions]]&lt;br /&gt;
* [[WriteBinaryFile]]&lt;br /&gt;
* [[CurrentDataFolder]]&lt;br /&gt;
* [[Model File Character Encoding]]&lt;br /&gt;
* [[Files and Editing]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64020</id>
		<title>MakeJSON</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64020"/>
		<updated>2026-06-25T14:20:01Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Correct flag 512 polarity to opt-out (base64 is the default; setting 512 keeps the legacy «Picture» placeholder), matching the code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Text Functions]]&lt;br /&gt;
[[category:Analytica 5.0]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''New to [[Analytica 5.0]]''&lt;br /&gt;
&lt;br /&gt;
{{Release|1=|2=6.5|3=''This function requires the {{Analytica Developer}} edition or higher (i.e., higher editions are [[Analytica Optimizer Guide|Analytica Optimizer]], [[Analytica Decision Engine|ADE]] or [http://Cubeplan.com CubePlan]]).''}}&lt;br /&gt;
&lt;br /&gt;
== MakeJSON( x'', indexOrder, objects, flags{{Release|7.1||, maxCells}}'' ) ==&lt;br /&gt;
&lt;br /&gt;
Returns text in [http://json.org JavaScript Object Notation (JSON)]] format representing the data in «x». When there are multidimensional arrays, you can control the nesting order in the JSON text by specifying the indexes in the «indexOrder» parameter. When some indexes encode the member names of a JavaScript object, you should list those indexes in «objects». The optional «flags» parameter accepts an integer that encodes a bit-field of options, with these options.&lt;br /&gt;
* 1 = Don't infer that 1-D arrays with textual indexes are objects.&lt;br /&gt;
* 2 = reserved. Must be 0. &amp;lt;!-- Reserved for; Return a schema --&amp;gt;&lt;br /&gt;
* 4 = reserved. Should be 0. &amp;lt;!-- Reserved for: Issue an error if there is an object inconsistency.--&amp;gt;&lt;br /&gt;
* 8 = Top-level element in the result can be a non-object.&lt;br /&gt;
* 16 = Allow ragged arrays.{{Release|6.4||&lt;br /&gt;
* 32 {{=}} Don't include fields that have a [[Null]] value.}}{{Release|6.5||&lt;br /&gt;
* 64 {{=}} Prepend a dot to local index identifier text values.}}{{Release|7.0||&lt;br /&gt;
* 128 {{=}} Allow preformatted JSON. Reference to text gets inserted verbatim.}}{{Release|7.1||&lt;br /&gt;
* 256 {{=}} Escape CR as \r. Without the flag, it escapes as \n as generally required in JavaScript.}}{{Release|1=7.1|2=|3=&lt;br /&gt;
* 512 = Don't encode picture or binary-image data as base64 -- keep the legacy &amp;lt;code&amp;gt;&amp;quot;«Picture (PNG)»&amp;quot;&amp;lt;/code&amp;gt; placeholder instead. Without this flag (the default), such data is emitted in a base64 form such as &amp;lt;code&amp;gt;{&amp;quot;width&amp;quot;:16, &amp;quot;height&amp;quot;:16, &amp;quot;mime&amp;quot;:&amp;quot;image/png&amp;quot;, &amp;quot;base64&amp;quot;:&amp;quot;iVBOR....&amp;quot;}&amp;lt;/code&amp;gt;.&lt;br /&gt;
* 1024 = Don't encode binary (non-image) data as base64. Without this flag (the default), binary data is emitted as &amp;lt;code&amp;gt;{&amp;quot;binary&amp;quot;:true, &amp;quot;base64&amp;quot;:&amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt; JSON objects.}}&lt;br /&gt;
&lt;br /&gt;
{{Release|7.1||The optional «maxCells» parameter limits how large an array may be before its contents are written out. When the total number of cells in an array -- the product of the lengths of all its indexes, across every dimension -- exceeds «maxCells», that array's elements are not serialized; instead a JSON object naming the array's true shape is emitted in its place:&lt;br /&gt;
:&amp;lt;code&amp;gt;{&amp;quot;$truncated&amp;quot;:true, &amp;quot;cells&amp;quot;:''N'', &amp;quot;maxCells&amp;quot;:''M'', &amp;quot;dimensions&amp;quot;:[{&amp;quot;index&amp;quot;:&amp;quot;''I''&amp;quot;, &amp;quot;size&amp;quot;:''n''}, ...]}&amp;lt;/code&amp;gt;&lt;br /&gt;
A positional or implicit index appears as &amp;lt;code&amp;gt;&amp;quot;index&amp;quot;:null&amp;lt;/code&amp;gt;. This guards against accidentally serializing an unintentionally enormous array (for example, millions of cells produced by a mistaken expression) into a huge JSON string. When «maxCells» is omitted, there is no limit.}}&lt;br /&gt;
&lt;br /&gt;
=== JSON Objects vs. Arrays ===&lt;br /&gt;
&lt;br /&gt;
Consider the following array in Variable &amp;lt;code&amp;gt;Biblio1984&amp;lt;/code&amp;gt;&lt;br /&gt;
:[[image:MakeJSON_Biblio1984.png]]&lt;br /&gt;
&lt;br /&gt;
One way to encode this is JSON is an a JSON object.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, objects: Biblio )&amp;lt;/code&amp;gt; &amp;amp;rarr; &lt;br /&gt;
:::&amp;lt;code&amp;gt;'{&amp;quot;title&amp;quot;: &amp;quot;1984&amp;quot;, &amp;quot;author&amp;quot;: &amp;quot;George Orwell&amp;quot;, &amp;quot;year&amp;quot;: 1949, &amp;quot;pages&amp;quot;: 336, &amp;quot;paperback&amp;quot;: 1}'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A second way to encode the same array data is an a JSON array.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, indexOrder:Biblio, flags:9 )&amp;lt;/code&amp;gt; &amp;amp;rarr;&lt;br /&gt;
:::&amp;lt;code&amp;gt;'[&amp;quot;1984&amp;quot;, &amp;quot;George Orwell&amp;quot;, 1949, 336, 1]'&amp;lt;/code&amp;gt;&lt;br /&gt;
Because the top-most item in JSON text is supposed to a JSON object, this second example isn't strictly valid (the «flags»=8 option was required for this reason). But for information anywhere other than the outermost dimension of «x», the fact remains that the data in an Analytica array can be placed in either form -- JSON-object or JSON-array.&lt;br /&gt;
&lt;br /&gt;
For any index in your data, you can make it explicit by listing the index in the «objects» parameter if you want it to produce a JSON object, or in the «indexOrder» parameter if you want it to produce a JSON-array for that index.  When you don't set the «flags»=8 bit, one index will be selected as an object index, even if they are all listed in «indexOrder», just because JSON text is supposed to have the root be an object.&lt;br /&gt;
&lt;br /&gt;
When «x» contains an index that you have not explicitly listed, it will infer that it should be an object when the «flags»=1 is not set, the array is 1-D, and the index has textual member names. Otherwise it will output it as an array without the index labels.&lt;br /&gt;
&lt;br /&gt;
=== Index order ===&lt;br /&gt;
&lt;br /&gt;
When an Analytica array has more that one-dimension, you should list the indexes in «indexOrder», with the index that should vary most slowly listed first. For example:&lt;br /&gt;
&lt;br /&gt;
 Index I := &amp;lt;code&amp;gt;1..4&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index  J := &amp;lt;code&amp;gt;1..3&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index K := &amp;lt;code&amp;gt;['k1', 'k2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z1 := &amp;lt;code&amp;gt;10 * J + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z2 := &amp;lt;code&amp;gt;100*I + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index Struct := &amp;lt;code&amp;gt;['z1', 'z2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable data1 := [[Table]](Struct)( \z1, \z2 )&lt;br /&gt;
&lt;br /&gt;
You should think of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; as being like an instantiation of a class named &amp;lt;code&amp;gt;Struct&amp;lt;/code&amp;gt;, which has two members &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; member of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;J, K&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;I, K&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you don't specify the index order, you can't reliably predict which nesting you will get.&lt;br /&gt;
 [[MakeJSON]]( data1 ) &amp;amp;rarr;&lt;br /&gt;
      { &amp;quot;z1&amp;quot;: [[11, 12], [21, 22], [31, 32]], &lt;br /&gt;
        &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
      }&lt;br /&gt;
Note: [[MakeJSON]] does not insert newlines or indents. The result was formatted above manually.&lt;br /&gt;
&lt;br /&gt;
It may be that the application code receiving this expects the data to be in &amp;lt;code&amp;gt;K&amp;lt;/code&amp;gt;-major order. In the above, &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; was as desired, but &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; was transposed. To ensure this, you need to specify the «indexOrder».&lt;br /&gt;
 [[MakeJSON]]( data1, indexOrder: K, J, I ) &amp;amp;rarr;&lt;br /&gt;
 { &amp;quot;z1&amp;quot;: [[11, 21, 31], [12, 22, 32]], &lt;br /&gt;
   &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
When you list multiple indexes in the «objects» parameter, this also constrains the order, where the first index listed becomes the outer object. For example, given the following Analytica array&lt;br /&gt;
:[[image:MakeJSON_cat_dog.png]]&lt;br /&gt;
listing &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; before &amp;lt;code&amp;gt;Sex&amp;lt;/code&amp;gt; in «objects» creates nested objects as follows&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Animal,Sex)&amp;amp;rarr;{&amp;quot;cat&amp;quot;: {&amp;quot;Male&amp;quot;: 12, &amp;quot;Female&amp;quot;: 8}, &amp;quot;dog&amp;quot;: {&amp;quot;Male&amp;quot;: 4, &amp;quot;Female&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
but listing them in the opposite order reverses the object nesting&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Sex,Animal)&amp;amp;rarr;{&amp;quot;Male&amp;quot;: {&amp;quot;cat&amp;quot;: 12, &amp;quot;dog&amp;quot;: 4}, &amp;quot;Female&amp;quot;: {&amp;quot;cat&amp;quot;: 8, &amp;quot;dog&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mixed objects and arrays ===&lt;br /&gt;
(These rules apply to [[Analytica 5.2]]. Before that, it isn't legit to have object &amp;amp; array dimensions mixed for single arrays -- instead, you should use references to structure your object structures).&lt;br /&gt;
&lt;br /&gt;
When a multi-dimensional array is transcribed into JSON at any level (each time there is a reference, you have a new multi-dimensional array to consider), each index of that array will be transcribed either as a JSON array or as a JSON object (i.e., either using brackets [ ] or using braces { } ). By using the «indexOrder» and «objects» parameters, you have control over which way each index is treated, as well as the nesting order. You could, for example, end up with an array of JSON objects, or a JSON object containing arrays for each member.&lt;br /&gt;
&lt;br /&gt;
The rules for selecting whether an index is treated as an JSON object or JSON array is as follows:&lt;br /&gt;
* An index listed in «objects» will be transcribed as an object.&lt;br /&gt;
* When the array is 1-D and &amp;lt;code&amp;gt;flags:1&amp;lt;/code&amp;gt; is not set and the index labels are textual, an index not listed in «indexOrder_» is treated as an object.&lt;br /&gt;
* When &amp;lt;code&amp;gt;flags:8&amp;lt;/code&amp;gt; is not set, the very first index of the entire JSON is an object.&lt;br /&gt;
* Otherwise, it is transcribed as an array.&lt;br /&gt;
&lt;br /&gt;
The rules for determining nesting order are as follows:&lt;br /&gt;
* If index I appears before index J in the «indexOrder» parameter, then J will be nested inside I.&lt;br /&gt;
* If index I appears before index J in the «objects» parameter, then J will be nested inside I.&lt;br /&gt;
* When two indexes aren't explicitly ordered in one of the two parameters, objects are nested inside array dimensions (i.e., objects moved inward, array dimensions moved outward), so you'll end up with arrays of objects.&lt;br /&gt;
* Finally, Analytica's internal canonical ordering is used. Since this is internal to Analytica, this is essentially an arbitrary ordering.&lt;br /&gt;
&lt;br /&gt;
When you need to specify the nesting order between a JSON-array and a JSON-object dimension, list both corresponding indexes in the «indexOrder» parameter and list the index for the object in the «objects» parameter.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ParseJSON]]&lt;br /&gt;
* [[MakeCSV]]&lt;br /&gt;
* [[WriteTextFile]]&lt;br /&gt;
* [[JoinText]], [[NumberToText]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64019</id>
		<title>MakeJSON</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64019"/>
		<updated>2026-06-25T00:24:28Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document flag 1024 (opt out of base64 encoding for binary data; keeps the legacy placeholder)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Text Functions]]&lt;br /&gt;
[[category:Analytica 5.0]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''New to [[Analytica 5.0]]''&lt;br /&gt;
&lt;br /&gt;
{{Release|1=|2=6.5|3=''This function requires the {{Analytica Developer}} edition or higher (i.e., higher editions are [[Analytica Optimizer Guide|Analytica Optimizer]], [[Analytica Decision Engine|ADE]] or [http://Cubeplan.com CubePlan]]).''}}&lt;br /&gt;
&lt;br /&gt;
== MakeJSON( x'', indexOrder, objects, flags{{Release|7.1||, maxCells}}'' ) ==&lt;br /&gt;
&lt;br /&gt;
Returns text in [http://json.org JavaScript Object Notation (JSON)]] format representing the data in «x». When there are multidimensional arrays, you can control the nesting order in the JSON text by specifying the indexes in the «indexOrder» parameter. When some indexes encode the member names of a JavaScript object, you should list those indexes in «objects». The optional «flags» parameter accepts an integer that encodes a bit-field of options, with these options.&lt;br /&gt;
* 1 = Don't infer that 1-D arrays with textual indexes are objects.&lt;br /&gt;
* 2 = reserved. Must be 0. &amp;lt;!-- Reserved for; Return a schema --&amp;gt;&lt;br /&gt;
* 4 = reserved. Should be 0. &amp;lt;!-- Reserved for: Issue an error if there is an object inconsistency.--&amp;gt;&lt;br /&gt;
* 8 = Top-level element in the result can be a non-object.&lt;br /&gt;
* 16 = Allow ragged arrays.{{Release|6.4||&lt;br /&gt;
* 32 {{=}} Don't include fields that have a [[Null]] value.}}{{Release|6.5||&lt;br /&gt;
* 64 {{=}} Prepend a dot to local index identifier text values.}}{{Release|7.0||&lt;br /&gt;
* 128 {{=}} Allow preformatted JSON. Reference to text gets inserted verbatim.}}{{Release|7.1||&lt;br /&gt;
* 256 {{=}} Escape CR as \r. Without the flag, it escapes as \n as generally required in JavaScript.}}{{Release|1=7.1|2=|3=&lt;br /&gt;
* 512 = Encode images in a base64 form such as &amp;lt;code&amp;gt;{&amp;quot;width&amp;quot;:16, &amp;quot;height&amp;quot;:16, &amp;quot;mime&amp;quot;:&amp;quot;image/png&amp;quot;, &amp;quot;base64&amp;quot;:&amp;quot;iVBOR....&amp;quot;}&amp;lt;/code&amp;gt;. Without this they appear as &amp;lt;code&amp;gt;&amp;quot;«Picture (PNG)»&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* 1024 = Don't encode binary (non-image) data as base64. Without this flag (the default), binary data is emitted as &amp;lt;code&amp;gt;{&amp;quot;binary&amp;quot;:true, &amp;quot;base64&amp;quot;:&amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt; JSON objects.}}&lt;br /&gt;
&lt;br /&gt;
{{Release|7.1||The optional «maxCells» parameter limits how large an array may be before its contents are written out. When the total number of cells in an array -- the product of the lengths of all its indexes, across every dimension -- exceeds «maxCells», that array's elements are not serialized; instead a JSON object naming the array's true shape is emitted in its place:&lt;br /&gt;
:&amp;lt;code&amp;gt;{&amp;quot;$truncated&amp;quot;:true, &amp;quot;cells&amp;quot;:''N'', &amp;quot;maxCells&amp;quot;:''M'', &amp;quot;dimensions&amp;quot;:[{&amp;quot;index&amp;quot;:&amp;quot;''I''&amp;quot;, &amp;quot;size&amp;quot;:''n''}, ...]}&amp;lt;/code&amp;gt;&lt;br /&gt;
A positional or implicit index appears as &amp;lt;code&amp;gt;&amp;quot;index&amp;quot;:null&amp;lt;/code&amp;gt;. This guards against accidentally serializing an unintentionally enormous array (for example, millions of cells produced by a mistaken expression) into a huge JSON string. When «maxCells» is omitted, there is no limit.}}&lt;br /&gt;
&lt;br /&gt;
=== JSON Objects vs. Arrays ===&lt;br /&gt;
&lt;br /&gt;
Consider the following array in Variable &amp;lt;code&amp;gt;Biblio1984&amp;lt;/code&amp;gt;&lt;br /&gt;
:[[image:MakeJSON_Biblio1984.png]]&lt;br /&gt;
&lt;br /&gt;
One way to encode this is JSON is an a JSON object.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, objects: Biblio )&amp;lt;/code&amp;gt; &amp;amp;rarr; &lt;br /&gt;
:::&amp;lt;code&amp;gt;'{&amp;quot;title&amp;quot;: &amp;quot;1984&amp;quot;, &amp;quot;author&amp;quot;: &amp;quot;George Orwell&amp;quot;, &amp;quot;year&amp;quot;: 1949, &amp;quot;pages&amp;quot;: 336, &amp;quot;paperback&amp;quot;: 1}'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A second way to encode the same array data is an a JSON array.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, indexOrder:Biblio, flags:9 )&amp;lt;/code&amp;gt; &amp;amp;rarr;&lt;br /&gt;
:::&amp;lt;code&amp;gt;'[&amp;quot;1984&amp;quot;, &amp;quot;George Orwell&amp;quot;, 1949, 336, 1]'&amp;lt;/code&amp;gt;&lt;br /&gt;
Because the top-most item in JSON text is supposed to a JSON object, this second example isn't strictly valid (the «flags»=8 option was required for this reason). But for information anywhere other than the outermost dimension of «x», the fact remains that the data in an Analytica array can be placed in either form -- JSON-object or JSON-array.&lt;br /&gt;
&lt;br /&gt;
For any index in your data, you can make it explicit by listing the index in the «objects» parameter if you want it to produce a JSON object, or in the «indexOrder» parameter if you want it to produce a JSON-array for that index.  When you don't set the «flags»=8 bit, one index will be selected as an object index, even if they are all listed in «indexOrder», just because JSON text is supposed to have the root be an object.&lt;br /&gt;
&lt;br /&gt;
When «x» contains an index that you have not explicitly listed, it will infer that it should be an object when the «flags»=1 is not set, the array is 1-D, and the index has textual member names. Otherwise it will output it as an array without the index labels.&lt;br /&gt;
&lt;br /&gt;
=== Index order ===&lt;br /&gt;
&lt;br /&gt;
When an Analytica array has more that one-dimension, you should list the indexes in «indexOrder», with the index that should vary most slowly listed first. For example:&lt;br /&gt;
&lt;br /&gt;
 Index I := &amp;lt;code&amp;gt;1..4&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index  J := &amp;lt;code&amp;gt;1..3&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index K := &amp;lt;code&amp;gt;['k1', 'k2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z1 := &amp;lt;code&amp;gt;10 * J + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z2 := &amp;lt;code&amp;gt;100*I + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index Struct := &amp;lt;code&amp;gt;['z1', 'z2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable data1 := [[Table]](Struct)( \z1, \z2 )&lt;br /&gt;
&lt;br /&gt;
You should think of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; as being like an instantiation of a class named &amp;lt;code&amp;gt;Struct&amp;lt;/code&amp;gt;, which has two members &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; member of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;J, K&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;I, K&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you don't specify the index order, you can't reliably predict which nesting you will get.&lt;br /&gt;
 [[MakeJSON]]( data1 ) &amp;amp;rarr;&lt;br /&gt;
      { &amp;quot;z1&amp;quot;: [[11, 12], [21, 22], [31, 32]], &lt;br /&gt;
        &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
      }&lt;br /&gt;
Note: [[MakeJSON]] does not insert newlines or indents. The result was formatted above manually.&lt;br /&gt;
&lt;br /&gt;
It may be that the application code receiving this expects the data to be in &amp;lt;code&amp;gt;K&amp;lt;/code&amp;gt;-major order. In the above, &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; was as desired, but &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; was transposed. To ensure this, you need to specify the «indexOrder».&lt;br /&gt;
 [[MakeJSON]]( data1, indexOrder: K, J, I ) &amp;amp;rarr;&lt;br /&gt;
 { &amp;quot;z1&amp;quot;: [[11, 21, 31], [12, 22, 32]], &lt;br /&gt;
   &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
When you list multiple indexes in the «objects» parameter, this also constrains the order, where the first index listed becomes the outer object. For example, given the following Analytica array&lt;br /&gt;
:[[image:MakeJSON_cat_dog.png]]&lt;br /&gt;
listing &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; before &amp;lt;code&amp;gt;Sex&amp;lt;/code&amp;gt; in «objects» creates nested objects as follows&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Animal,Sex)&amp;amp;rarr;{&amp;quot;cat&amp;quot;: {&amp;quot;Male&amp;quot;: 12, &amp;quot;Female&amp;quot;: 8}, &amp;quot;dog&amp;quot;: {&amp;quot;Male&amp;quot;: 4, &amp;quot;Female&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
but listing them in the opposite order reverses the object nesting&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Sex,Animal)&amp;amp;rarr;{&amp;quot;Male&amp;quot;: {&amp;quot;cat&amp;quot;: 12, &amp;quot;dog&amp;quot;: 4}, &amp;quot;Female&amp;quot;: {&amp;quot;cat&amp;quot;: 8, &amp;quot;dog&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mixed objects and arrays ===&lt;br /&gt;
(These rules apply to [[Analytica 5.2]]. Before that, it isn't legit to have object &amp;amp; array dimensions mixed for single arrays -- instead, you should use references to structure your object structures).&lt;br /&gt;
&lt;br /&gt;
When a multi-dimensional array is transcribed into JSON at any level (each time there is a reference, you have a new multi-dimensional array to consider), each index of that array will be transcribed either as a JSON array or as a JSON object (i.e., either using brackets [ ] or using braces { } ). By using the «indexOrder» and «objects» parameters, you have control over which way each index is treated, as well as the nesting order. You could, for example, end up with an array of JSON objects, or a JSON object containing arrays for each member.&lt;br /&gt;
&lt;br /&gt;
The rules for selecting whether an index is treated as an JSON object or JSON array is as follows:&lt;br /&gt;
* An index listed in «objects» will be transcribed as an object.&lt;br /&gt;
* When the array is 1-D and &amp;lt;code&amp;gt;flags:1&amp;lt;/code&amp;gt; is not set and the index labels are textual, an index not listed in «indexOrder_» is treated as an object.&lt;br /&gt;
* When &amp;lt;code&amp;gt;flags:8&amp;lt;/code&amp;gt; is not set, the very first index of the entire JSON is an object.&lt;br /&gt;
* Otherwise, it is transcribed as an array.&lt;br /&gt;
&lt;br /&gt;
The rules for determining nesting order are as follows:&lt;br /&gt;
* If index I appears before index J in the «indexOrder» parameter, then J will be nested inside I.&lt;br /&gt;
* If index I appears before index J in the «objects» parameter, then J will be nested inside I.&lt;br /&gt;
* When two indexes aren't explicitly ordered in one of the two parameters, objects are nested inside array dimensions (i.e., objects moved inward, array dimensions moved outward), so you'll end up with arrays of objects.&lt;br /&gt;
* Finally, Analytica's internal canonical ordering is used. Since this is internal to Analytica, this is essentially an arbitrary ordering.&lt;br /&gt;
&lt;br /&gt;
When you need to specify the nesting order between a JSON-array and a JSON-object dimension, list both corresponding indexes in the «indexOrder» parameter and list the index for the object in the «objects» parameter.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ParseJSON]]&lt;br /&gt;
* [[MakeCSV]]&lt;br /&gt;
* [[WriteTextFile]]&lt;br /&gt;
* [[JoinText]], [[NumberToText]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=64018</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=64018"/>
		<updated>2026-06-25T00:18:43Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Built-in functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page lists new features in release 7.1, which is currently in early [[Beta Tester Page|Beta Testing]].  If have have an active subscription license, we encourage you to try it out from the [[Beta Tester Page]].&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
* There is a new option, '''Use as default arrow style''', on the right-mouse context menu for an influence diagram arrow. This sets the global arrow style default to match the selected arrow.&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image. Also there is a new «maxCells» parameter that can be used to prevent giagantic arrays from being encoded (resulting in immensely long text).&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
* Added a syntax construct for [[Namespaces#Scoped_namespace_inclusion:_Using|Scoped namespace inclusion]] to bring a namespace into scope for only a localized expression or lexical block.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64017</id>
		<title>MakeJSON</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64017"/>
		<updated>2026-06-25T00:17:10Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Text Functions]]&lt;br /&gt;
[[category:Analytica 5.0]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''New to [[Analytica 5.0]]''&lt;br /&gt;
&lt;br /&gt;
{{Release|1=|2=6.5|3=''This function requires the {{Analytica Developer}} edition or higher (i.e., higher editions are [[Analytica Optimizer Guide|Analytica Optimizer]], [[Analytica Decision Engine|ADE]] or [http://Cubeplan.com CubePlan]]).''}}&lt;br /&gt;
&lt;br /&gt;
== MakeJSON( x'', indexOrder, objects, flags{{Release|7.1||, maxCells}}'' ) ==&lt;br /&gt;
&lt;br /&gt;
Returns text in [http://json.org JavaScript Object Notation (JSON)]] format representing the data in «x». When there are multidimensional arrays, you can control the nesting order in the JSON text by specifying the indexes in the «indexOrder» parameter. When some indexes encode the member names of a JavaScript object, you should list those indexes in «objects». The optional «flags» parameter accepts an integer that encodes a bit-field of options, with these options.&lt;br /&gt;
* 1 = Don't infer that 1-D arrays with textual indexes are objects.&lt;br /&gt;
* 2 = reserved. Must be 0. &amp;lt;!-- Reserved for; Return a schema --&amp;gt;&lt;br /&gt;
* 4 = reserved. Should be 0. &amp;lt;!-- Reserved for: Issue an error if there is an object inconsistency.--&amp;gt;&lt;br /&gt;
* 8 = Top-level element in the result can be a non-object.&lt;br /&gt;
* 16 = Allow ragged arrays.{{Release|6.4||&lt;br /&gt;
* 32 {{=}} Don't include fields that have a [[Null]] value.}}{{Release|6.5||&lt;br /&gt;
* 64 {{=}} Prepend a dot to local index identifier text values.}}{{Release|7.0||&lt;br /&gt;
* 128 {{=}} Allow preformatted JSON. Reference to text gets inserted verbatim.}}{{Release|7.1||&lt;br /&gt;
* 256 {{=}} Escape CR as \r. Without the flag, it escapes as \n as generally required in JavaScript.}}{{Release|1=7.1|2=|3=&lt;br /&gt;
* 512 = Encode images in a base64 form such as &amp;lt;code&amp;gt;{&amp;quot;width&amp;quot;:16, &amp;quot;height&amp;quot;:16, &amp;quot;mime&amp;quot;:&amp;quot;image/png&amp;quot;, &amp;quot;base64&amp;quot;:&amp;quot;iVBOR....&amp;quot;}&amp;lt;/code&amp;gt;. Without this they appear as &amp;lt;code&amp;gt;&amp;quot;«Picture (PNG)»&amp;quot;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Release|7.1||The optional «maxCells» parameter limits how large an array may be before its contents are written out. When the total number of cells in an array -- the product of the lengths of all its indexes, across every dimension -- exceeds «maxCells», that array's elements are not serialized; instead a JSON object naming the array's true shape is emitted in its place:&lt;br /&gt;
:&amp;lt;code&amp;gt;{&amp;quot;$truncated&amp;quot;:true, &amp;quot;cells&amp;quot;:''N'', &amp;quot;maxCells&amp;quot;:''M'', &amp;quot;dimensions&amp;quot;:[{&amp;quot;index&amp;quot;:&amp;quot;''I''&amp;quot;, &amp;quot;size&amp;quot;:''n''}, ...]}&amp;lt;/code&amp;gt;&lt;br /&gt;
A positional or implicit index appears as &amp;lt;code&amp;gt;&amp;quot;index&amp;quot;:null&amp;lt;/code&amp;gt;. This guards against accidentally serializing an unintentionally enormous array (for example, millions of cells produced by a mistaken expression) into a huge JSON string. When «maxCells» is omitted, there is no limit.}}&lt;br /&gt;
&lt;br /&gt;
=== JSON Objects vs. Arrays ===&lt;br /&gt;
&lt;br /&gt;
Consider the following array in Variable &amp;lt;code&amp;gt;Biblio1984&amp;lt;/code&amp;gt;&lt;br /&gt;
:[[image:MakeJSON_Biblio1984.png]]&lt;br /&gt;
&lt;br /&gt;
One way to encode this is JSON is an a JSON object.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, objects: Biblio )&amp;lt;/code&amp;gt; &amp;amp;rarr; &lt;br /&gt;
:::&amp;lt;code&amp;gt;'{&amp;quot;title&amp;quot;: &amp;quot;1984&amp;quot;, &amp;quot;author&amp;quot;: &amp;quot;George Orwell&amp;quot;, &amp;quot;year&amp;quot;: 1949, &amp;quot;pages&amp;quot;: 336, &amp;quot;paperback&amp;quot;: 1}'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A second way to encode the same array data is an a JSON array.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, indexOrder:Biblio, flags:9 )&amp;lt;/code&amp;gt; &amp;amp;rarr;&lt;br /&gt;
:::&amp;lt;code&amp;gt;'[&amp;quot;1984&amp;quot;, &amp;quot;George Orwell&amp;quot;, 1949, 336, 1]'&amp;lt;/code&amp;gt;&lt;br /&gt;
Because the top-most item in JSON text is supposed to a JSON object, this second example isn't strictly valid (the «flags»=8 option was required for this reason). But for information anywhere other than the outermost dimension of «x», the fact remains that the data in an Analytica array can be placed in either form -- JSON-object or JSON-array.&lt;br /&gt;
&lt;br /&gt;
For any index in your data, you can make it explicit by listing the index in the «objects» parameter if you want it to produce a JSON object, or in the «indexOrder» parameter if you want it to produce a JSON-array for that index.  When you don't set the «flags»=8 bit, one index will be selected as an object index, even if they are all listed in «indexOrder», just because JSON text is supposed to have the root be an object.&lt;br /&gt;
&lt;br /&gt;
When «x» contains an index that you have not explicitly listed, it will infer that it should be an object when the «flags»=1 is not set, the array is 1-D, and the index has textual member names. Otherwise it will output it as an array without the index labels.&lt;br /&gt;
&lt;br /&gt;
=== Index order ===&lt;br /&gt;
&lt;br /&gt;
When an Analytica array has more that one-dimension, you should list the indexes in «indexOrder», with the index that should vary most slowly listed first. For example:&lt;br /&gt;
&lt;br /&gt;
 Index I := &amp;lt;code&amp;gt;1..4&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index  J := &amp;lt;code&amp;gt;1..3&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index K := &amp;lt;code&amp;gt;['k1', 'k2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z1 := &amp;lt;code&amp;gt;10 * J + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z2 := &amp;lt;code&amp;gt;100*I + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index Struct := &amp;lt;code&amp;gt;['z1', 'z2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable data1 := [[Table]](Struct)( \z1, \z2 )&lt;br /&gt;
&lt;br /&gt;
You should think of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; as being like an instantiation of a class named &amp;lt;code&amp;gt;Struct&amp;lt;/code&amp;gt;, which has two members &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; member of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;J, K&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;I, K&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you don't specify the index order, you can't reliably predict which nesting you will get.&lt;br /&gt;
 [[MakeJSON]]( data1 ) &amp;amp;rarr;&lt;br /&gt;
      { &amp;quot;z1&amp;quot;: [[11, 12], [21, 22], [31, 32]], &lt;br /&gt;
        &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
      }&lt;br /&gt;
Note: [[MakeJSON]] does not insert newlines or indents. The result was formatted above manually.&lt;br /&gt;
&lt;br /&gt;
It may be that the application code receiving this expects the data to be in &amp;lt;code&amp;gt;K&amp;lt;/code&amp;gt;-major order. In the above, &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; was as desired, but &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; was transposed. To ensure this, you need to specify the «indexOrder».&lt;br /&gt;
 [[MakeJSON]]( data1, indexOrder: K, J, I ) &amp;amp;rarr;&lt;br /&gt;
 { &amp;quot;z1&amp;quot;: [[11, 21, 31], [12, 22, 32]], &lt;br /&gt;
   &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
When you list multiple indexes in the «objects» parameter, this also constrains the order, where the first index listed becomes the outer object. For example, given the following Analytica array&lt;br /&gt;
:[[image:MakeJSON_cat_dog.png]]&lt;br /&gt;
listing &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; before &amp;lt;code&amp;gt;Sex&amp;lt;/code&amp;gt; in «objects» creates nested objects as follows&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Animal,Sex)&amp;amp;rarr;{&amp;quot;cat&amp;quot;: {&amp;quot;Male&amp;quot;: 12, &amp;quot;Female&amp;quot;: 8}, &amp;quot;dog&amp;quot;: {&amp;quot;Male&amp;quot;: 4, &amp;quot;Female&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
but listing them in the opposite order reverses the object nesting&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Sex,Animal)&amp;amp;rarr;{&amp;quot;Male&amp;quot;: {&amp;quot;cat&amp;quot;: 12, &amp;quot;dog&amp;quot;: 4}, &amp;quot;Female&amp;quot;: {&amp;quot;cat&amp;quot;: 8, &amp;quot;dog&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mixed objects and arrays ===&lt;br /&gt;
(These rules apply to [[Analytica 5.2]]. Before that, it isn't legit to have object &amp;amp; array dimensions mixed for single arrays -- instead, you should use references to structure your object structures).&lt;br /&gt;
&lt;br /&gt;
When a multi-dimensional array is transcribed into JSON at any level (each time there is a reference, you have a new multi-dimensional array to consider), each index of that array will be transcribed either as a JSON array or as a JSON object (i.e., either using brackets [ ] or using braces { } ). By using the «indexOrder» and «objects» parameters, you have control over which way each index is treated, as well as the nesting order. You could, for example, end up with an array of JSON objects, or a JSON object containing arrays for each member.&lt;br /&gt;
&lt;br /&gt;
The rules for selecting whether an index is treated as an JSON object or JSON array is as follows:&lt;br /&gt;
* An index listed in «objects» will be transcribed as an object.&lt;br /&gt;
* When the array is 1-D and &amp;lt;code&amp;gt;flags:1&amp;lt;/code&amp;gt; is not set and the index labels are textual, an index not listed in «indexOrder_» is treated as an object.&lt;br /&gt;
* When &amp;lt;code&amp;gt;flags:8&amp;lt;/code&amp;gt; is not set, the very first index of the entire JSON is an object.&lt;br /&gt;
* Otherwise, it is transcribed as an array.&lt;br /&gt;
&lt;br /&gt;
The rules for determining nesting order are as follows:&lt;br /&gt;
* If index I appears before index J in the «indexOrder» parameter, then J will be nested inside I.&lt;br /&gt;
* If index I appears before index J in the «objects» parameter, then J will be nested inside I.&lt;br /&gt;
* When two indexes aren't explicitly ordered in one of the two parameters, objects are nested inside array dimensions (i.e., objects moved inward, array dimensions moved outward), so you'll end up with arrays of objects.&lt;br /&gt;
* Finally, Analytica's internal canonical ordering is used. Since this is internal to Analytica, this is essentially an arbitrary ordering.&lt;br /&gt;
&lt;br /&gt;
When you need to specify the nesting order between a JSON-array and a JSON-object dimension, list both corresponding indexes in the «indexOrder» parameter and list the index for the object in the «objects» parameter.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ParseJSON]]&lt;br /&gt;
* [[MakeCSV]]&lt;br /&gt;
* [[WriteTextFile]]&lt;br /&gt;
* [[JoinText]], [[NumberToText]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64016</id>
		<title>MakeJSON</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=MakeJSON&amp;diff=64016"/>
		<updated>2026-06-25T00:15:33Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document the new maxCells parameter (caps array serialization; oversized arrays become a {&amp;quot;$truncated&amp;quot;:...} descriptor)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Text Functions]]&lt;br /&gt;
[[category:Analytica 5.0]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''New to [[Analytica 5.0]]''&lt;br /&gt;
&lt;br /&gt;
{{Release|1=|2=6.5|3=''This function requires the {{Analytica Developer}} edition or higher (i.e., higher editions are [[Analytica Optimizer Guide|Analytica Optimizer]], [[Analytica Decision Engine|ADE]] or [http://Cubeplan.com CubePlan]]).''}}&lt;br /&gt;
&lt;br /&gt;
== MakeJSON( x'', indexOrder, objects, flags, maxCells'' ) ==&lt;br /&gt;
&lt;br /&gt;
Returns text in [http://json.org JavaScript Object Notation (JSON)]] format representing the data in «x». When there are multidimensional arrays, you can control the nesting order in the JSON text by specifying the indexes in the «indexOrder» parameter. When some indexes encode the member names of a JavaScript object, you should list those indexes in «objects». The optional «flags» parameter accepts an integer that encodes a bit-field of options, with these options.&lt;br /&gt;
* 1 = Don't infer that 1-D arrays with textual indexes are objects.&lt;br /&gt;
* 2 = reserved. Must be 0. &amp;lt;!-- Reserved for; Return a schema --&amp;gt;&lt;br /&gt;
* 4 = reserved. Should be 0. &amp;lt;!-- Reserved for: Issue an error if there is an object inconsistency.--&amp;gt;&lt;br /&gt;
* 8 = Top-level element in the result can be a non-object.&lt;br /&gt;
* 16 = Allow ragged arrays.{{Release|6.4||&lt;br /&gt;
* 32 {{=}} Don't include fields that have a [[Null]] value.}}{{Release|6.5||&lt;br /&gt;
* 64 {{=}} Prepend a dot to local index identifier text values.}}{{Release|7.0||&lt;br /&gt;
* 128 {{=}} Allow preformatted JSON. Reference to text gets inserted verbatim.}}{{Release|7.1||&lt;br /&gt;
* 256 {{=}} Escape CR as \r. Without the flag, it escapes as \n as generally required in JavaScript.}}{{Release|1=7.1|2=|3=&lt;br /&gt;
* 512 = Encode images in a base64 form such as &amp;lt;code&amp;gt;{&amp;quot;width&amp;quot;:16, &amp;quot;height&amp;quot;:16, &amp;quot;mime&amp;quot;:&amp;quot;image/png&amp;quot;, &amp;quot;base64&amp;quot;:&amp;quot;iVBOR....&amp;quot;}&amp;lt;/code&amp;gt;. Without this they appear as &amp;lt;code&amp;gt;&amp;quot;«Picture (PNG)»&amp;quot;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Release|7.1||The optional «maxCells» parameter limits how large an array may be before its contents are written out. When the total number of cells in an array -- the product of the lengths of all its indexes, across every dimension -- exceeds «maxCells», that array's elements are not serialized; instead a JSON object naming the array's true shape is emitted in its place:&lt;br /&gt;
:&amp;lt;code&amp;gt;{&amp;quot;$truncated&amp;quot;:true, &amp;quot;cells&amp;quot;:''N'', &amp;quot;maxCells&amp;quot;:''M'', &amp;quot;dimensions&amp;quot;:[{&amp;quot;index&amp;quot;:&amp;quot;''I''&amp;quot;, &amp;quot;size&amp;quot;:''n''}, ...]}&amp;lt;/code&amp;gt;&lt;br /&gt;
A positional or implicit index appears as &amp;lt;code&amp;gt;&amp;quot;index&amp;quot;:null&amp;lt;/code&amp;gt;. This guards against accidentally serializing an unintentionally enormous array (for example, millions of cells produced by a mistaken expression) into a huge JSON string. When «maxCells» is omitted, there is no limit.}}&lt;br /&gt;
&lt;br /&gt;
=== JSON Objects vs. Arrays ===&lt;br /&gt;
&lt;br /&gt;
Consider the following array in Variable &amp;lt;code&amp;gt;Biblio1984&amp;lt;/code&amp;gt;&lt;br /&gt;
:[[image:MakeJSON_Biblio1984.png]]&lt;br /&gt;
&lt;br /&gt;
One way to encode this is JSON is an a JSON object.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, objects: Biblio )&amp;lt;/code&amp;gt; &amp;amp;rarr; &lt;br /&gt;
:::&amp;lt;code&amp;gt;'{&amp;quot;title&amp;quot;: &amp;quot;1984&amp;quot;, &amp;quot;author&amp;quot;: &amp;quot;George Orwell&amp;quot;, &amp;quot;year&amp;quot;: 1949, &amp;quot;pages&amp;quot;: 336, &amp;quot;paperback&amp;quot;: 1}'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A second way to encode the same array data is an a JSON array.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]]( Biblio1984, indexOrder:Biblio, flags:9 )&amp;lt;/code&amp;gt; &amp;amp;rarr;&lt;br /&gt;
:::&amp;lt;code&amp;gt;'[&amp;quot;1984&amp;quot;, &amp;quot;George Orwell&amp;quot;, 1949, 336, 1]'&amp;lt;/code&amp;gt;&lt;br /&gt;
Because the top-most item in JSON text is supposed to a JSON object, this second example isn't strictly valid (the «flags»=8 option was required for this reason). But for information anywhere other than the outermost dimension of «x», the fact remains that the data in an Analytica array can be placed in either form -- JSON-object or JSON-array.&lt;br /&gt;
&lt;br /&gt;
For any index in your data, you can make it explicit by listing the index in the «objects» parameter if you want it to produce a JSON object, or in the «indexOrder» parameter if you want it to produce a JSON-array for that index.  When you don't set the «flags»=8 bit, one index will be selected as an object index, even if they are all listed in «indexOrder», just because JSON text is supposed to have the root be an object.&lt;br /&gt;
&lt;br /&gt;
When «x» contains an index that you have not explicitly listed, it will infer that it should be an object when the «flags»=1 is not set, the array is 1-D, and the index has textual member names. Otherwise it will output it as an array without the index labels.&lt;br /&gt;
&lt;br /&gt;
=== Index order ===&lt;br /&gt;
&lt;br /&gt;
When an Analytica array has more that one-dimension, you should list the indexes in «indexOrder», with the index that should vary most slowly listed first. For example:&lt;br /&gt;
&lt;br /&gt;
 Index I := &amp;lt;code&amp;gt;1..4&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index  J := &amp;lt;code&amp;gt;1..3&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index K := &amp;lt;code&amp;gt;['k1', 'k2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z1 := &amp;lt;code&amp;gt;10 * J + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable z2 := &amp;lt;code&amp;gt;100*I + @K&amp;lt;/code&amp;gt;&lt;br /&gt;
 Index Struct := &amp;lt;code&amp;gt;['z1', 'z2']&amp;lt;/code&amp;gt;&lt;br /&gt;
 Variable data1 := [[Table]](Struct)( \z1, \z2 )&lt;br /&gt;
&lt;br /&gt;
You should think of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; as being like an instantiation of a class named &amp;lt;code&amp;gt;Struct&amp;lt;/code&amp;gt;, which has two members &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; member of &amp;lt;code&amp;gt;data1&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;J, K&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; has a 2-D array indexed by &amp;lt;code&amp;gt;I, K&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you don't specify the index order, you can't reliably predict which nesting you will get.&lt;br /&gt;
 [[MakeJSON]]( data1 ) &amp;amp;rarr;&lt;br /&gt;
      { &amp;quot;z1&amp;quot;: [[11, 12], [21, 22], [31, 32]], &lt;br /&gt;
        &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
      }&lt;br /&gt;
Note: [[MakeJSON]] does not insert newlines or indents. The result was formatted above manually.&lt;br /&gt;
&lt;br /&gt;
It may be that the application code receiving this expects the data to be in &amp;lt;code&amp;gt;K&amp;lt;/code&amp;gt;-major order. In the above, &amp;lt;code&amp;gt;z2&amp;lt;/code&amp;gt; was as desired, but &amp;lt;code&amp;gt;z1&amp;lt;/code&amp;gt; was transposed. To ensure this, you need to specify the «indexOrder».&lt;br /&gt;
 [[MakeJSON]]( data1, indexOrder: K, J, I ) &amp;amp;rarr;&lt;br /&gt;
 { &amp;quot;z1&amp;quot;: [[11, 21, 31], [12, 22, 32]], &lt;br /&gt;
   &amp;quot;z2&amp;quot;: [[101, 201, 301, 401], [102, 202, 302, 402]]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
When you list multiple indexes in the «objects» parameter, this also constrains the order, where the first index listed becomes the outer object. For example, given the following Analytica array&lt;br /&gt;
:[[image:MakeJSON_cat_dog.png]]&lt;br /&gt;
listing &amp;lt;code&amp;gt;Animal&amp;lt;/code&amp;gt; before &amp;lt;code&amp;gt;Sex&amp;lt;/code&amp;gt; in «objects» creates nested objects as follows&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Animal,Sex)&amp;amp;rarr;{&amp;quot;cat&amp;quot;: {&amp;quot;Male&amp;quot;: 12, &amp;quot;Female&amp;quot;: 8}, &amp;quot;dog&amp;quot;: {&amp;quot;Male&amp;quot;: 4, &amp;quot;Female&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
but listing them in the opposite order reverses the object nesting&lt;br /&gt;
:&amp;lt;code&amp;gt;[[MakeJSON]](Counts, objects:Sex,Animal)&amp;amp;rarr;{&amp;quot;Male&amp;quot;: {&amp;quot;cat&amp;quot;: 12, &amp;quot;dog&amp;quot;: 4}, &amp;quot;Female&amp;quot;: {&amp;quot;cat&amp;quot;: 8, &amp;quot;dog&amp;quot;: 5}}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mixed objects and arrays ===&lt;br /&gt;
(These rules apply to [[Analytica 5.2]]. Before that, it isn't legit to have object &amp;amp; array dimensions mixed for single arrays -- instead, you should use references to structure your object structures).&lt;br /&gt;
&lt;br /&gt;
When a multi-dimensional array is transcribed into JSON at any level (each time there is a reference, you have a new multi-dimensional array to consider), each index of that array will be transcribed either as a JSON array or as a JSON object (i.e., either using brackets [ ] or using braces { } ). By using the «indexOrder» and «objects» parameters, you have control over which way each index is treated, as well as the nesting order. You could, for example, end up with an array of JSON objects, or a JSON object containing arrays for each member.&lt;br /&gt;
&lt;br /&gt;
The rules for selecting whether an index is treated as an JSON object or JSON array is as follows:&lt;br /&gt;
* An index listed in «objects» will be transcribed as an object.&lt;br /&gt;
* When the array is 1-D and &amp;lt;code&amp;gt;flags:1&amp;lt;/code&amp;gt; is not set and the index labels are textual, an index not listed in «indexOrder_» is treated as an object.&lt;br /&gt;
* When &amp;lt;code&amp;gt;flags:8&amp;lt;/code&amp;gt; is not set, the very first index of the entire JSON is an object.&lt;br /&gt;
* Otherwise, it is transcribed as an array.&lt;br /&gt;
&lt;br /&gt;
The rules for determining nesting order are as follows:&lt;br /&gt;
* If index I appears before index J in the «indexOrder» parameter, then J will be nested inside I.&lt;br /&gt;
* If index I appears before index J in the «objects» parameter, then J will be nested inside I.&lt;br /&gt;
* When two indexes aren't explicitly ordered in one of the two parameters, objects are nested inside array dimensions (i.e., objects moved inward, array dimensions moved outward), so you'll end up with arrays of objects.&lt;br /&gt;
* Finally, Analytica's internal canonical ordering is used. Since this is internal to Analytica, this is essentially an arbitrary ordering.&lt;br /&gt;
&lt;br /&gt;
When you need to specify the nesting order between a JSON-array and a JSON-object dimension, list both corresponding indexes in the «indexOrder» parameter and list the index for the object in the «objects» parameter.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ParseJSON]]&lt;br /&gt;
* [[MakeCSV]]&lt;br /&gt;
* [[WriteTextFile]]&lt;br /&gt;
* [[JoinText]], [[NumberToText]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64007</id>
		<title>QFlex distribution</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64007"/>
		<updated>2026-06-23T23:38:00Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Add download links for library and demo model&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Continuous distributions]]&lt;br /&gt;
[[category:Unbounded distributions]]&lt;br /&gt;
[[category:Bounded distributions]]&lt;br /&gt;
[[category:Semi-bounded distributions]]&lt;br /&gt;
[[category:Univariate distributions]]&lt;br /&gt;
[[category:Custom distributions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''Provided by a downloadable add-in library (not a built-in distribution). Fitting requires the [[Analytica Optimizer]] edition.''&lt;br /&gt;
&lt;br /&gt;
== QFlex( a, ''K, gamma, lb, ub'' ) ==&lt;br /&gt;
&lt;br /&gt;
The ''QFlex distribution'' (&amp;quot;Quantile Flexibility&amp;quot;) is a flexible, quantile-parameterized distribution capable of fitting a wide variety of continuous shapes directly to a set of assessed quantiles — for example a 10-50-90 judgment, or a larger set of assessed percentiles. Use it when standard parametric distributions such as the [[Normal distribution|Normal]], [[Log-normal distribution|LogNormal]], or [[Beta distribution|Beta]] are too restrictive to match what you have assessed, and you want a single smooth distribution that passes through (or near) your elicited quantiles while remaining a valid probability distribution.&lt;br /&gt;
&lt;br /&gt;
You obtain the coefficient vector «a» by fitting it to your assessed quantiles with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; (see [[#How to use the library|How to use the library]] below). &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; then draws a sampled, uncertain value from the fitted distribution, much as you would use a built-in distribution like &amp;lt;code&amp;gt;Normal&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LogNormal&amp;lt;/code&amp;gt;. Define a Chance variable as &amp;lt;code&amp;gt;QFlex(...)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
;Reference&lt;br /&gt;
:Bickel, J. Eric, Connor Colombe, and Benjamin D. Leibowicz. ''The QFlex Distribution.'' The University of Texas at Austin. '''(Under review for publication, June 2026.)'''&lt;br /&gt;
:''The QFlex distribution and the methods implemented in this library are described in this paper. Because the paper is currently in review, the citation details may change.''&lt;br /&gt;
&lt;br /&gt;
'''QFlex is not a built-in Analytica distribution.''' It is provided as a downloadable [[Libraries|library]] (see [[#Download and installation|Download and installation]]). Because the coefficient fit is solved as a quadratic program (QP), the [[Analytica Optimizer]] edition is required to fit a QFlex distribution to your data.&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
* «a»: The QFlex coefficient vector, indexed by «K». You normally obtain this from &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «K»: The coefficient [[Index]]. Its length is the maximum number of terms. Use, e.g., &amp;lt;code&amp;gt;K := 1..10&amp;lt;/code&amp;gt;. (A 1-term QFlex is not a valid distribution, so use at least 2; more terms give a more flexible fit.)&lt;br /&gt;
* «gamma»: (Optional, default 0.5): The centering parameter. Use the same «gamma» that you used when fitting «a». See &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «lb», «ub»: (Optional): The support bounds. Omit both for an '''unbounded''' distribution; supply «lb» only for a '''lower-bounded''' [«lb», ∞) distribution; supply both for a '''bounded''' [«lb», «ub»] distribution.&lt;br /&gt;
&lt;br /&gt;
== About the QFlex distribution ==&lt;br /&gt;
&lt;br /&gt;
Internally, QFlex builds the distribution's quantile function (the inverse CDF) as a weighted sum of simple, individually valid building blocks: powers of a right-tail exponential, a left-tail (reflected) exponential, and a centered-uniform term. Because every building block is itself a valid, strictly increasing quantile function, a QFlex fit can be kept '''monotone — a genuine probability distribution — by construction''', through simple conditions on its coefficients. This is its main practical advantage over some other flexible quantile-parameterized families such as the [[Keelin (MetaLog) distribution|Keelin (MetaLog)]] distribution, which can require more complex constraints to ensure monotonicity. (Note that the Keelin distribution in Analytica automatically enforces these). &lt;br /&gt;
&lt;br /&gt;
Consider QFlex when:&lt;br /&gt;
* You have '''more assessed (or empirical) quantiles than a standard 2-3 parameter distribution can honor''', and you want the distribution to match them rather than only approximate their mean and spread.&lt;br /&gt;
* You want a '''smooth, valid continuous distribution''' (with an analytic CDF and PDF) rather than a discrete or purely empirical one.&lt;br /&gt;
* You need '''control over skewness and tail behavior''', or want to shape the left tail, right tail, and center somewhat independently.&lt;br /&gt;
* Your quantity is '''unbounded, lower-bounded, or bounded''' — QFlex supports all three.&lt;br /&gt;
&lt;br /&gt;
The number of terms (the length of «K») controls flexibility: more terms can match more assessed quantiles and more complex shapes. With «K» terms you can interpolate up to «K» probability-quantile pairs; with more assessed pairs than terms, the fit is a constrained least-squares fit. You do '''not''' need to work through the paper's mathematics to use the library — the functions encapsulate the fitting and the analytic details for practical model building.&lt;br /&gt;
&lt;br /&gt;
Since the [[Keelin (MetaLog) distribution]] and QFlex are both highly flexible with largely the same underpinning motivations, the question of when to use one or the other arises. In general, the MetaLog distribution exhibits a greater degree of flexibility, and is more apt to capture distributional variation (and a comparable number of terms), whereas QFlex tends towards a strong unimodal bias and is less likely to display wiggle that may (or may not) actually be present. Both distributions exhibit strong matching to classic Pearson distributions, with QFlex showing a somewhat stronger bias to shapes within the Pearson space. In Analytica, for now, QFlex requires the Optimizer edition whereas MetaLog is available in all editions. For those who have to implement their own code in a different platform, QFlex is easier to implement than MetaLog 2.0.&lt;br /&gt;
&lt;br /&gt;
== Download and installation ==&lt;br /&gt;
&lt;br /&gt;
QFlex is distributed as an Analytica library plus a demonstration model, both plain &amp;lt;code&amp;gt;.ana&amp;lt;/code&amp;gt; files:&lt;br /&gt;
* '''Library:''' &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; [https://downloads.analytica.com/AdditionalLibraries/QFlex%20distribution%20library.ana Download]&lt;br /&gt;
* '''Demo model:''' &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; [https://downloads.analytica.com/AdditionalLibraries/Demo%20of%20QFlex%20distribution.ana Download]&lt;br /&gt;
&lt;br /&gt;
To use the library in your own model, open your model and choose '''File &amp;amp;rarr; Add Library...''', select &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt;, and link it. The library's functions then become available in your model. The demo model already includes the library and shows the full workflow.&lt;br /&gt;
&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
* '''[[Analytica Optimizer]] edition.''' The fitting function &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; solves a quadratic program, which requires Optimizer. (Once you have a fitted coefficient vector, the remaining functions — &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; — are ordinary evaluations and do not themselves require Optimizer; but in normal use you fit with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;, so Optimizer is required.)&lt;br /&gt;
* Analytica 7.x or later is recommended.&lt;br /&gt;
&lt;br /&gt;
== How to use the library ==&lt;br /&gt;
&lt;br /&gt;
The workflow has three steps:&lt;br /&gt;
&lt;br /&gt;
# '''Compute the centering parameter «gamma».''' Use &amp;lt;code&amp;gt;QFlexEstimateGamma( p, q, I )&amp;lt;/code&amp;gt; on your assessed probability-quantile pairs, or specify a «gamma» yourself if you have a preferred value. Keep that «gamma» and pass the '''same''' value to the later functions.&lt;br /&gt;
# '''Fit the coefficient vector «a».''' Use &amp;lt;code&amp;gt;QFlexFit( p, q, I, K, gamma, numTerms )&amp;lt;/code&amp;gt; with your probabilities «p», quantiles «q», the assessment index «I», and the coefficient index «K». ''(This step requires the Optimizer edition.)''&lt;br /&gt;
# '''Use the fitted distribution.''' Call &amp;lt;code&amp;gt;QFlex( a, K, gamma, lb, ub )&amp;lt;/code&amp;gt; to construct the uncertain quantity, or use &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; for the inverse CDF, CDF, and density at specific points. Use the '''same «gamma» and «K»''' that you used when fitting.&lt;br /&gt;
&lt;br /&gt;
Because «gamma» is an explicit parameter to the QFlex functions, it is best to compute or choose «gamma» once and then pass that same value consistently to the fitting and evaluation functions.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Fit to assessed quantiles ===&lt;br /&gt;
&lt;br /&gt;
Suppose you have assessed ten quantiles of an uncertain quantity. Define an index of the assessed probabilities, the assessed quantile values, and a coefficient index:&lt;br /&gt;
&lt;br /&gt;
:Index Quantile_probability := &amp;lt;code&amp;gt;[0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99, 0.999]&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable Assessed_quantiles := &amp;lt;code&amp;gt;Table( Quantile_probability )( ... )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''(your ten assessed quantile values)''&lt;br /&gt;
:Index K_terms := &amp;lt;code&amp;gt;1..10&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then carry out the three steps:&lt;br /&gt;
&lt;br /&gt;
:Variable Gamma_to_use := &amp;lt;code&amp;gt;QFlexEstimateGamma( Quantile_probability, Assessed_quantiles, Quantile_probability )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable QFlex_coefficients := &amp;lt;code&amp;gt;QFlexFit( Quantile_probability, Assessed_quantiles, Quantile_probability, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Chance Fitted_distribution := &amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;Fitted_distribution&amp;lt;/code&amp;gt; is an uncertain quantity you can use anywhere in your model. You can also read the fitted distribution analytically at specific points:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the fitted 90th percentile''&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the CDF, P(X &amp;amp;le; x)''&lt;br /&gt;
:&amp;lt;code&amp;gt;DensQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the density (PDF) at x''&lt;br /&gt;
&lt;br /&gt;
=== Bounded and semi-bounded fits ===&lt;br /&gt;
&lt;br /&gt;
To fit a distribution known to be non-negative (for example, a cost or a physical quantity), pass a lower bound to the construction and evaluation functions:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''lower-bounded at 0''&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0, ub: 100 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''bounded on [0, 100]''&lt;br /&gt;
&lt;br /&gt;
Use the same «lb» and «ub» consistently across &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; so they all describe the same distribution.&lt;br /&gt;
&lt;br /&gt;
== Fitting the distribution to your data ==&lt;br /&gt;
&lt;br /&gt;
These two functions are used '''before''' constructing the distribution, to estimate the centering parameter and fit the coefficients.&lt;br /&gt;
&lt;br /&gt;
=== QFlexEstimateGamma( p, q, I ) ===&lt;br /&gt;
&lt;br /&gt;
Estimates the QFlex centering parameter «gamma» from assessed probability-quantile pairs («p», «q») indexed by «I». It estimates Q(0.1), Q(0.5), and Q(0.9) from your assessed quantiles by interpolation, computes the Kelly skewness index ''SI'', and returns gamma = 0.5 &amp;amp;times; (1 &amp;amp;minus; ''SI''), clipped to the open interval (0, 1).&lt;br /&gt;
&lt;br /&gt;
* «p»: The assessed probabilities, each in (0, 1), indexed by «I».&lt;br /&gt;
* «q»: The corresponding assessed quantile values, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
&lt;br /&gt;
Returns gamma = 0.5 for a symmetric assessment with no skew (0.45 in the exactly symmetric case, matching the paper's convention), a value greater than 0.5 for right-skewed assessments, and less than 0.5 for left-skewed ones. If fewer than three points are supplied, it returns 0.5.&lt;br /&gt;
&lt;br /&gt;
''Why «gamma» matters:'' it centers the centered-uniform basis terms. Choosing «gamma» from the assessed skewness (rather than always 0.5) keeps the fit well-conditioned — important especially when your assessed probabilities are symmetric about 0.5.&lt;br /&gt;
&lt;br /&gt;
=== QFlexFit( p, q, I, K, ''gamma, numTerms'' ) ===&lt;br /&gt;
&lt;br /&gt;
Fits the QFlex coefficient vector «a» (indexed by «K») to your assessed pairs («p», «q») by constrained least squares: it minimizes squared quantile error subject to the monotonicity constraints (tail-coefficient nonnegativity and the tail-center magnitude bound) from the paper, so the fitted distribution is '''valid by construction'''. '''Requires the [[Analytica Optimizer]] edition''' (the fit is a QP).&lt;br /&gt;
&lt;br /&gt;
* «p», «q»: The assessed probabilities and quantiles, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
* «K»: The coefficient [[Index]]; its length sets the maximum number of terms.&lt;br /&gt;
* «gamma»: (Optional): The centering parameter. If omitted, &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; estimates it internally via &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;. '''Best practice:''' compute «gamma» once with &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt; and pass it explicitly, so the same value is used for both fitting and evaluation.&lt;br /&gt;
* «numTerms»: (Optional): How many terms (&amp;amp;le; &amp;lt;code&amp;gt;IndexLength(K)&amp;lt;/code&amp;gt;) to actually fit. If omitted, all of «K» is used. If «numTerms» is less than the length of «K», the result is still indexed by «K» and is &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in the positions beyond «numTerms».&lt;br /&gt;
&lt;br /&gt;
'''Returns''' the coefficient vector «a» indexed by «K» (with &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in any unused positions). Pass this vector, with the same «K» and «gamma», to &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Analytic distribution functions ==&lt;br /&gt;
&lt;br /&gt;
These functions evaluate the fitted distribution analytically at a point (or an array of points), without sampling. They all take the fitted coefficient vector «a» indexed by «K», the centering parameter «gamma», and the same optional bounds «lb»/«ub» described under [[#QFlex( a, K, gamma, lb, ub )|QFlex]].&lt;br /&gt;
&lt;br /&gt;
=== CumQFlexInv( p, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''inverse cumulative (quantile) function''': returns the value «x» such that P(X &amp;amp;le; «x») = «p». Evaluate it at a probability «p» (or an array of probabilities) to read quantiles off the fitted distribution. This is the closed-form construction; &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; simply calls it with a uniform random «p».&lt;br /&gt;
&lt;br /&gt;
* «p»: A probability in [0, 1] (or an array of them).&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; returns the fitted 90th percentile.&lt;br /&gt;
&lt;br /&gt;
=== CumQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''cumulative distribution function''': returns P(X &amp;amp;le; «x») for a value «x». It is computed by numerically inverting the quantile function (bisection), giving the analytic CDF at a point, independent of sampling.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the CDF.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlex( 0, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DensQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''probability density function''' f(«x»): returns the density at a value «x», using the quantile-density relationship (no sampling required). This is convenient for plotting a smooth PDF curve over a grid of «x» values.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the density.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;DensQFlex( Plot_x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note on bounds:''' An upper bound must be supplied together with a lower bound. Specifying «ub» without «lb» is not supported, and the analytic CDF/PDF return &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in that case. For an upper-bounded quantity, use the bounded [«lb», «ub»] form.&lt;br /&gt;
&lt;br /&gt;
== The demo model ==&lt;br /&gt;
&lt;br /&gt;
The demo model &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; provides an interactive playground:&lt;br /&gt;
* Editable assessed quantiles for several example data sets (a symmetric logistic, a right-skewed lognormal, a heavy-tailed Student-''t'', and two bimodal shapes), selectable individually.&lt;br /&gt;
* A number-of-terms control to explore how flexibility changes the fit.&lt;br /&gt;
* Live graphs of the fitted inverse CDF, CDF, and PDF, built from &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A QA-tests module with analytically tractable checks (for example, the coefficient vector «a» = [0, 1, 1] reproduces the standard logistic quantile), useful as worked sanity checks.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Keelin (MetaLog) distribution]] &amp;amp;mdash; a related quantile-parameterized distribution.&lt;br /&gt;
* [[UncertainLMH]] &amp;amp;mdash; simpler option when you have only a low-medium-high (e.g. 10-50-90) assessment.&lt;br /&gt;
* [[Analytica Optimizer]] &amp;amp;mdash; the edition required for fitting.&lt;br /&gt;
* [[Distribution Densities Library]]&lt;br /&gt;
* [[Probability Distributions]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64006</id>
		<title>QFlex distribution</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64006"/>
		<updated>2026-06-23T23:30:03Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* About the QFlex distribution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Continuous distributions]]&lt;br /&gt;
[[category:Unbounded distributions]]&lt;br /&gt;
[[category:Bounded distributions]]&lt;br /&gt;
[[category:Semi-bounded distributions]]&lt;br /&gt;
[[category:Univariate distributions]]&lt;br /&gt;
[[category:Custom distributions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''Provided by a downloadable add-in library (not a built-in distribution). Fitting requires the [[Analytica Optimizer]] edition.''&lt;br /&gt;
&lt;br /&gt;
== QFlex( a, ''K, gamma, lb, ub'' ) ==&lt;br /&gt;
&lt;br /&gt;
The ''QFlex distribution'' (&amp;quot;Quantile Flexibility&amp;quot;) is a flexible, quantile-parameterized distribution capable of fitting a wide variety of continuous shapes directly to a set of assessed quantiles — for example a 10-50-90 judgment, or a larger set of assessed percentiles. Use it when standard parametric distributions such as the [[Normal distribution|Normal]], [[Log-normal distribution|LogNormal]], or [[Beta distribution|Beta]] are too restrictive to match what you have assessed, and you want a single smooth distribution that passes through (or near) your elicited quantiles while remaining a valid probability distribution.&lt;br /&gt;
&lt;br /&gt;
You obtain the coefficient vector «a» by fitting it to your assessed quantiles with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; (see [[#How to use the library|How to use the library]] below). &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; then draws a sampled, uncertain value from the fitted distribution, much as you would use a built-in distribution like &amp;lt;code&amp;gt;Normal&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LogNormal&amp;lt;/code&amp;gt;. Define a Chance variable as &amp;lt;code&amp;gt;QFlex(...)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
;Reference&lt;br /&gt;
:Bickel, J. Eric, Connor Colombe, and Benjamin D. Leibowicz. ''The QFlex Distribution.'' The University of Texas at Austin. '''(Under review for publication, June 2026.)'''&lt;br /&gt;
:''The QFlex distribution and the methods implemented in this library are described in this paper. Because the paper is currently in review, the citation details may change.''&lt;br /&gt;
&lt;br /&gt;
'''QFlex is not a built-in Analytica distribution.''' It is provided as a downloadable [[Libraries|library]] (see [[#Download and installation|Download and installation]]). Because the coefficient fit is solved as a quadratic program (QP), the [[Analytica Optimizer]] edition is required to fit a QFlex distribution to your data.&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
* «a»: The QFlex coefficient vector, indexed by «K». You normally obtain this from &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «K»: The coefficient [[Index]]. Its length is the maximum number of terms. Use, e.g., &amp;lt;code&amp;gt;K := 1..10&amp;lt;/code&amp;gt;. (A 1-term QFlex is not a valid distribution, so use at least 2; more terms give a more flexible fit.)&lt;br /&gt;
* «gamma»: (Optional, default 0.5): The centering parameter. Use the same «gamma» that you used when fitting «a». See &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «lb», «ub»: (Optional): The support bounds. Omit both for an '''unbounded''' distribution; supply «lb» only for a '''lower-bounded''' [«lb», ∞) distribution; supply both for a '''bounded''' [«lb», «ub»] distribution.&lt;br /&gt;
&lt;br /&gt;
== About the QFlex distribution ==&lt;br /&gt;
&lt;br /&gt;
Internally, QFlex builds the distribution's quantile function (the inverse CDF) as a weighted sum of simple, individually valid building blocks: powers of a right-tail exponential, a left-tail (reflected) exponential, and a centered-uniform term. Because every building block is itself a valid, strictly increasing quantile function, a QFlex fit can be kept '''monotone — a genuine probability distribution — by construction''', through simple conditions on its coefficients. This is its main practical advantage over some other flexible quantile-parameterized families such as the [[Keelin (MetaLog) distribution|Keelin (MetaLog)]] distribution, which can require more complex constraints to ensure monotonicity. (Note that the Keelin distribution in Analytica automatically enforces these). &lt;br /&gt;
&lt;br /&gt;
Consider QFlex when:&lt;br /&gt;
* You have '''more assessed (or empirical) quantiles than a standard 2-3 parameter distribution can honor''', and you want the distribution to match them rather than only approximate their mean and spread.&lt;br /&gt;
* You want a '''smooth, valid continuous distribution''' (with an analytic CDF and PDF) rather than a discrete or purely empirical one.&lt;br /&gt;
* You need '''control over skewness and tail behavior''', or want to shape the left tail, right tail, and center somewhat independently.&lt;br /&gt;
* Your quantity is '''unbounded, lower-bounded, or bounded''' — QFlex supports all three.&lt;br /&gt;
&lt;br /&gt;
The number of terms (the length of «K») controls flexibility: more terms can match more assessed quantiles and more complex shapes. With «K» terms you can interpolate up to «K» probability-quantile pairs; with more assessed pairs than terms, the fit is a constrained least-squares fit. You do '''not''' need to work through the paper's mathematics to use the library — the functions encapsulate the fitting and the analytic details for practical model building.&lt;br /&gt;
&lt;br /&gt;
Since the [[Keelin (MetaLog) distribution]] and QFlex are both highly flexible with largely the same underpinning motivations, the question of when to use one or the other arises. In general, the MetaLog distribution exhibits a greater degree of flexibility, and is more apt to capture distributional variation (and a comparable number of terms), whereas QFlex tends towards a strong unimodal bias and is less likely to display wiggle that may (or may not) actually be present. Both distributions exhibit strong matching to classic Pearson distributions, with QFlex showing a somewhat stronger bias to shapes within the Pearson space. In Analytica, for now, QFlex requires the Optimizer edition whereas MetaLog is available in all editions. For those who have to implement their own code in a different platform, QFlex is easier to implement than MetaLog 2.0.&lt;br /&gt;
&lt;br /&gt;
== Download and installation ==&lt;br /&gt;
&lt;br /&gt;
QFlex is distributed as an Analytica library plus a demonstration model, both plain &amp;lt;code&amp;gt;.ana&amp;lt;/code&amp;gt; files:&lt;br /&gt;
* '''Library:''' &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; '''[download link to be added]'''&lt;br /&gt;
* '''Demo model:''' &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; '''[download link to be added]'''&lt;br /&gt;
&lt;br /&gt;
To use the library in your own model, open your model and choose '''File &amp;amp;rarr; Add Library...''', select &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt;, and link it. The library's functions then become available in your model. The demo model already includes the library and shows the full workflow.&lt;br /&gt;
&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
* '''[[Analytica Optimizer]] edition.''' The fitting function &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; solves a quadratic program, which requires Optimizer. (Once you have a fitted coefficient vector, the remaining functions — &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; — are ordinary evaluations and do not themselves require Optimizer; but in normal use you fit with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;, so Optimizer is required.)&lt;br /&gt;
* Analytica 7.x or later is recommended.&lt;br /&gt;
&lt;br /&gt;
== How to use the library ==&lt;br /&gt;
&lt;br /&gt;
The workflow has three steps:&lt;br /&gt;
&lt;br /&gt;
# '''Compute the centering parameter «gamma».''' Use &amp;lt;code&amp;gt;QFlexEstimateGamma( p, q, I )&amp;lt;/code&amp;gt; on your assessed probability-quantile pairs, or specify a «gamma» yourself if you have a preferred value. Keep that «gamma» and pass the '''same''' value to the later functions.&lt;br /&gt;
# '''Fit the coefficient vector «a».''' Use &amp;lt;code&amp;gt;QFlexFit( p, q, I, K, gamma, numTerms )&amp;lt;/code&amp;gt; with your probabilities «p», quantiles «q», the assessment index «I», and the coefficient index «K». ''(This step requires the Optimizer edition.)''&lt;br /&gt;
# '''Use the fitted distribution.''' Call &amp;lt;code&amp;gt;QFlex( a, K, gamma, lb, ub )&amp;lt;/code&amp;gt; to construct the uncertain quantity, or use &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; for the inverse CDF, CDF, and density at specific points. Use the '''same «gamma» and «K»''' that you used when fitting.&lt;br /&gt;
&lt;br /&gt;
Because «gamma» is an explicit parameter to the QFlex functions, it is best to compute or choose «gamma» once and then pass that same value consistently to the fitting and evaluation functions.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Fit to assessed quantiles ===&lt;br /&gt;
&lt;br /&gt;
Suppose you have assessed ten quantiles of an uncertain quantity. Define an index of the assessed probabilities, the assessed quantile values, and a coefficient index:&lt;br /&gt;
&lt;br /&gt;
:Index Quantile_probability := &amp;lt;code&amp;gt;[0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99, 0.999]&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable Assessed_quantiles := &amp;lt;code&amp;gt;Table( Quantile_probability )( ... )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''(your ten assessed quantile values)''&lt;br /&gt;
:Index K_terms := &amp;lt;code&amp;gt;1..10&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then carry out the three steps:&lt;br /&gt;
&lt;br /&gt;
:Variable Gamma_to_use := &amp;lt;code&amp;gt;QFlexEstimateGamma( Quantile_probability, Assessed_quantiles, Quantile_probability )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable QFlex_coefficients := &amp;lt;code&amp;gt;QFlexFit( Quantile_probability, Assessed_quantiles, Quantile_probability, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Chance Fitted_distribution := &amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;Fitted_distribution&amp;lt;/code&amp;gt; is an uncertain quantity you can use anywhere in your model. You can also read the fitted distribution analytically at specific points:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the fitted 90th percentile''&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the CDF, P(X &amp;amp;le; x)''&lt;br /&gt;
:&amp;lt;code&amp;gt;DensQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the density (PDF) at x''&lt;br /&gt;
&lt;br /&gt;
=== Bounded and semi-bounded fits ===&lt;br /&gt;
&lt;br /&gt;
To fit a distribution known to be non-negative (for example, a cost or a physical quantity), pass a lower bound to the construction and evaluation functions:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''lower-bounded at 0''&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0, ub: 100 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''bounded on [0, 100]''&lt;br /&gt;
&lt;br /&gt;
Use the same «lb» and «ub» consistently across &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; so they all describe the same distribution.&lt;br /&gt;
&lt;br /&gt;
== Fitting the distribution to your data ==&lt;br /&gt;
&lt;br /&gt;
These two functions are used '''before''' constructing the distribution, to estimate the centering parameter and fit the coefficients.&lt;br /&gt;
&lt;br /&gt;
=== QFlexEstimateGamma( p, q, I ) ===&lt;br /&gt;
&lt;br /&gt;
Estimates the QFlex centering parameter «gamma» from assessed probability-quantile pairs («p», «q») indexed by «I». It estimates Q(0.1), Q(0.5), and Q(0.9) from your assessed quantiles by interpolation, computes the Kelly skewness index ''SI'', and returns gamma = 0.5 &amp;amp;times; (1 &amp;amp;minus; ''SI''), clipped to the open interval (0, 1).&lt;br /&gt;
&lt;br /&gt;
* «p»: The assessed probabilities, each in (0, 1), indexed by «I».&lt;br /&gt;
* «q»: The corresponding assessed quantile values, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
&lt;br /&gt;
Returns gamma = 0.5 for a symmetric assessment with no skew (0.45 in the exactly symmetric case, matching the paper's convention), a value greater than 0.5 for right-skewed assessments, and less than 0.5 for left-skewed ones. If fewer than three points are supplied, it returns 0.5.&lt;br /&gt;
&lt;br /&gt;
''Why «gamma» matters:'' it centers the centered-uniform basis terms. Choosing «gamma» from the assessed skewness (rather than always 0.5) keeps the fit well-conditioned — important especially when your assessed probabilities are symmetric about 0.5.&lt;br /&gt;
&lt;br /&gt;
=== QFlexFit( p, q, I, K, ''gamma, numTerms'' ) ===&lt;br /&gt;
&lt;br /&gt;
Fits the QFlex coefficient vector «a» (indexed by «K») to your assessed pairs («p», «q») by constrained least squares: it minimizes squared quantile error subject to the monotonicity constraints (tail-coefficient nonnegativity and the tail-center magnitude bound) from the paper, so the fitted distribution is '''valid by construction'''. '''Requires the [[Analytica Optimizer]] edition''' (the fit is a QP).&lt;br /&gt;
&lt;br /&gt;
* «p», «q»: The assessed probabilities and quantiles, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
* «K»: The coefficient [[Index]]; its length sets the maximum number of terms.&lt;br /&gt;
* «gamma»: (Optional): The centering parameter. If omitted, &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; estimates it internally via &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;. '''Best practice:''' compute «gamma» once with &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt; and pass it explicitly, so the same value is used for both fitting and evaluation.&lt;br /&gt;
* «numTerms»: (Optional): How many terms (&amp;amp;le; &amp;lt;code&amp;gt;IndexLength(K)&amp;lt;/code&amp;gt;) to actually fit. If omitted, all of «K» is used. If «numTerms» is less than the length of «K», the result is still indexed by «K» and is &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in the positions beyond «numTerms».&lt;br /&gt;
&lt;br /&gt;
'''Returns''' the coefficient vector «a» indexed by «K» (with &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in any unused positions). Pass this vector, with the same «K» and «gamma», to &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Analytic distribution functions ==&lt;br /&gt;
&lt;br /&gt;
These functions evaluate the fitted distribution analytically at a point (or an array of points), without sampling. They all take the fitted coefficient vector «a» indexed by «K», the centering parameter «gamma», and the same optional bounds «lb»/«ub» described under [[#QFlex( a, K, gamma, lb, ub )|QFlex]].&lt;br /&gt;
&lt;br /&gt;
=== CumQFlexInv( p, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''inverse cumulative (quantile) function''': returns the value «x» such that P(X &amp;amp;le; «x») = «p». Evaluate it at a probability «p» (or an array of probabilities) to read quantiles off the fitted distribution. This is the closed-form construction; &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; simply calls it with a uniform random «p».&lt;br /&gt;
&lt;br /&gt;
* «p»: A probability in [0, 1] (or an array of them).&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; returns the fitted 90th percentile.&lt;br /&gt;
&lt;br /&gt;
=== CumQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''cumulative distribution function''': returns P(X &amp;amp;le; «x») for a value «x». It is computed by numerically inverting the quantile function (bisection), giving the analytic CDF at a point, independent of sampling.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the CDF.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlex( 0, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DensQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''probability density function''' f(«x»): returns the density at a value «x», using the quantile-density relationship (no sampling required). This is convenient for plotting a smooth PDF curve over a grid of «x» values.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the density.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;DensQFlex( Plot_x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note on bounds:''' An upper bound must be supplied together with a lower bound. Specifying «ub» without «lb» is not supported, and the analytic CDF/PDF return &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in that case. For an upper-bounded quantity, use the bounded [«lb», «ub»] form.&lt;br /&gt;
&lt;br /&gt;
== The demo model ==&lt;br /&gt;
&lt;br /&gt;
The demo model &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; provides an interactive playground:&lt;br /&gt;
* Editable assessed quantiles for several example data sets (a symmetric logistic, a right-skewed lognormal, a heavy-tailed Student-''t'', and two bimodal shapes), selectable individually.&lt;br /&gt;
* A number-of-terms control to explore how flexibility changes the fit.&lt;br /&gt;
* Live graphs of the fitted inverse CDF, CDF, and PDF, built from &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A QA-tests module with analytically tractable checks (for example, the coefficient vector «a» = [0, 1, 1] reproduces the standard logistic quantile), useful as worked sanity checks.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Keelin (MetaLog) distribution]] &amp;amp;mdash; a related quantile-parameterized distribution.&lt;br /&gt;
* [[UncertainLMH]] &amp;amp;mdash; simpler option when you have only a low-medium-high (e.g. 10-50-90) assessment.&lt;br /&gt;
* [[Analytica Optimizer]] &amp;amp;mdash; the edition required for fitting.&lt;br /&gt;
* [[Distribution Densities Library]]&lt;br /&gt;
* [[Probability Distributions]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64005</id>
		<title>QFlex distribution</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64005"/>
		<updated>2026-06-23T23:27:37Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* About the QFlex distribution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Continuous distributions]]&lt;br /&gt;
[[category:Unbounded distributions]]&lt;br /&gt;
[[category:Bounded distributions]]&lt;br /&gt;
[[category:Semi-bounded distributions]]&lt;br /&gt;
[[category:Univariate distributions]]&lt;br /&gt;
[[category:Custom distributions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''Provided by a downloadable add-in library (not a built-in distribution). Fitting requires the [[Analytica Optimizer]] edition.''&lt;br /&gt;
&lt;br /&gt;
== QFlex( a, ''K, gamma, lb, ub'' ) ==&lt;br /&gt;
&lt;br /&gt;
The ''QFlex distribution'' (&amp;quot;Quantile Flexibility&amp;quot;) is a flexible, quantile-parameterized distribution capable of fitting a wide variety of continuous shapes directly to a set of assessed quantiles — for example a 10-50-90 judgment, or a larger set of assessed percentiles. Use it when standard parametric distributions such as the [[Normal distribution|Normal]], [[Log-normal distribution|LogNormal]], or [[Beta distribution|Beta]] are too restrictive to match what you have assessed, and you want a single smooth distribution that passes through (or near) your elicited quantiles while remaining a valid probability distribution.&lt;br /&gt;
&lt;br /&gt;
You obtain the coefficient vector «a» by fitting it to your assessed quantiles with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; (see [[#How to use the library|How to use the library]] below). &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; then draws a sampled, uncertain value from the fitted distribution, much as you would use a built-in distribution like &amp;lt;code&amp;gt;Normal&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LogNormal&amp;lt;/code&amp;gt;. Define a Chance variable as &amp;lt;code&amp;gt;QFlex(...)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
;Reference&lt;br /&gt;
:Bickel, J. Eric, Connor Colombe, and Benjamin D. Leibowicz. ''The QFlex Distribution.'' The University of Texas at Austin. '''(Under review for publication, June 2026.)'''&lt;br /&gt;
:''The QFlex distribution and the methods implemented in this library are described in this paper. Because the paper is currently in review, the citation details may change.''&lt;br /&gt;
&lt;br /&gt;
'''QFlex is not a built-in Analytica distribution.''' It is provided as a downloadable [[Libraries|library]] (see [[#Download and installation|Download and installation]]). Because the coefficient fit is solved as a quadratic program (QP), the [[Analytica Optimizer]] edition is required to fit a QFlex distribution to your data.&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
* «a»: The QFlex coefficient vector, indexed by «K». You normally obtain this from &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «K»: The coefficient [[Index]]. Its length is the maximum number of terms. Use, e.g., &amp;lt;code&amp;gt;K := 1..10&amp;lt;/code&amp;gt;. (A 1-term QFlex is not a valid distribution, so use at least 2; more terms give a more flexible fit.)&lt;br /&gt;
* «gamma»: (Optional, default 0.5): The centering parameter. Use the same «gamma» that you used when fitting «a». See &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «lb», «ub»: (Optional): The support bounds. Omit both for an '''unbounded''' distribution; supply «lb» only for a '''lower-bounded''' [«lb», ∞) distribution; supply both for a '''bounded''' [«lb», «ub»] distribution.&lt;br /&gt;
&lt;br /&gt;
== About the QFlex distribution ==&lt;br /&gt;
&lt;br /&gt;
Internally, QFlex builds the distribution's quantile function (the inverse CDF) as a weighted sum of simple, individually valid building blocks: powers of a right-tail exponential, a left-tail (reflected) exponential, and a centered-uniform term. Because every building block is itself a valid, strictly increasing quantile function, a QFlex fit can be kept '''monotone — a genuine probability distribution — by construction''', through simple conditions on its coefficients. This is its main practical advantage over some other flexible quantile-parameterized families such as the [[Keelin (MetaLog) distribution|Keelin (MetaLog)]] distribution, which can require more complex constraints to ensure monotonicity. (Note that the Keelin distribution in Analytica automatically enforces these). &lt;br /&gt;
&lt;br /&gt;
Consider QFlex when:&lt;br /&gt;
* You have '''more assessed (or empirical) quantiles than a standard 2-3 parameter distribution can honor''', and you want the distribution to match them rather than only approximate their mean and spread.&lt;br /&gt;
* You want a '''smooth, valid continuous distribution''' (with an analytic CDF and PDF) rather than a discrete or purely empirical one.&lt;br /&gt;
* You need '''control over skewness and tail behavior''', or want to shape the left tail, right tail, and center somewhat independently.&lt;br /&gt;
* Your quantity is '''unbounded, lower-bounded, or bounded''' — QFlex supports all three.&lt;br /&gt;
&lt;br /&gt;
The number of terms (the length of «K») controls flexibility: more terms can match more assessed quantiles and more complex shapes. With «K» terms you can interpolate up to «K» probability-quantile pairs; with more assessed pairs than terms, the fit is a constrained least-squares fit. You do '''not''' need to work through the paper's mathematics to use the library — the functions encapsulate the fitting and the analytic details for practical model building.&lt;br /&gt;
&lt;br /&gt;
Since the [[Keelin (MetaLog) distribution]] and QFlex are both highly flexible with largely the same underpinning motivations, the question of when to use one or the other arises. In general, the MetaLog distribution exhibits a greater degree of flexibility, and is more apt to capture distributional variation (and a comparable number of terms), whereas QFlex tends towards a strong unimodal bias and is less likely to display wiggle that may (or may not) actually be present. Both distributions exhibit strong matching to classic Pearson distributions, with QFlex showing a somewhat stronger bias to shapes within the Pearson space.&lt;br /&gt;
&lt;br /&gt;
== Download and installation ==&lt;br /&gt;
&lt;br /&gt;
QFlex is distributed as an Analytica library plus a demonstration model, both plain &amp;lt;code&amp;gt;.ana&amp;lt;/code&amp;gt; files:&lt;br /&gt;
* '''Library:''' &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; '''[download link to be added]'''&lt;br /&gt;
* '''Demo model:''' &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; '''[download link to be added]'''&lt;br /&gt;
&lt;br /&gt;
To use the library in your own model, open your model and choose '''File &amp;amp;rarr; Add Library...''', select &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt;, and link it. The library's functions then become available in your model. The demo model already includes the library and shows the full workflow.&lt;br /&gt;
&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
* '''[[Analytica Optimizer]] edition.''' The fitting function &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; solves a quadratic program, which requires Optimizer. (Once you have a fitted coefficient vector, the remaining functions — &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; — are ordinary evaluations and do not themselves require Optimizer; but in normal use you fit with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;, so Optimizer is required.)&lt;br /&gt;
* Analytica 7.x or later is recommended.&lt;br /&gt;
&lt;br /&gt;
== How to use the library ==&lt;br /&gt;
&lt;br /&gt;
The workflow has three steps:&lt;br /&gt;
&lt;br /&gt;
# '''Compute the centering parameter «gamma».''' Use &amp;lt;code&amp;gt;QFlexEstimateGamma( p, q, I )&amp;lt;/code&amp;gt; on your assessed probability-quantile pairs, or specify a «gamma» yourself if you have a preferred value. Keep that «gamma» and pass the '''same''' value to the later functions.&lt;br /&gt;
# '''Fit the coefficient vector «a».''' Use &amp;lt;code&amp;gt;QFlexFit( p, q, I, K, gamma, numTerms )&amp;lt;/code&amp;gt; with your probabilities «p», quantiles «q», the assessment index «I», and the coefficient index «K». ''(This step requires the Optimizer edition.)''&lt;br /&gt;
# '''Use the fitted distribution.''' Call &amp;lt;code&amp;gt;QFlex( a, K, gamma, lb, ub )&amp;lt;/code&amp;gt; to construct the uncertain quantity, or use &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; for the inverse CDF, CDF, and density at specific points. Use the '''same «gamma» and «K»''' that you used when fitting.&lt;br /&gt;
&lt;br /&gt;
Because «gamma» is an explicit parameter to the QFlex functions, it is best to compute or choose «gamma» once and then pass that same value consistently to the fitting and evaluation functions.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Fit to assessed quantiles ===&lt;br /&gt;
&lt;br /&gt;
Suppose you have assessed ten quantiles of an uncertain quantity. Define an index of the assessed probabilities, the assessed quantile values, and a coefficient index:&lt;br /&gt;
&lt;br /&gt;
:Index Quantile_probability := &amp;lt;code&amp;gt;[0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99, 0.999]&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable Assessed_quantiles := &amp;lt;code&amp;gt;Table( Quantile_probability )( ... )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''(your ten assessed quantile values)''&lt;br /&gt;
:Index K_terms := &amp;lt;code&amp;gt;1..10&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then carry out the three steps:&lt;br /&gt;
&lt;br /&gt;
:Variable Gamma_to_use := &amp;lt;code&amp;gt;QFlexEstimateGamma( Quantile_probability, Assessed_quantiles, Quantile_probability )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable QFlex_coefficients := &amp;lt;code&amp;gt;QFlexFit( Quantile_probability, Assessed_quantiles, Quantile_probability, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Chance Fitted_distribution := &amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;Fitted_distribution&amp;lt;/code&amp;gt; is an uncertain quantity you can use anywhere in your model. You can also read the fitted distribution analytically at specific points:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the fitted 90th percentile''&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the CDF, P(X &amp;amp;le; x)''&lt;br /&gt;
:&amp;lt;code&amp;gt;DensQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the density (PDF) at x''&lt;br /&gt;
&lt;br /&gt;
=== Bounded and semi-bounded fits ===&lt;br /&gt;
&lt;br /&gt;
To fit a distribution known to be non-negative (for example, a cost or a physical quantity), pass a lower bound to the construction and evaluation functions:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''lower-bounded at 0''&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0, ub: 100 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''bounded on [0, 100]''&lt;br /&gt;
&lt;br /&gt;
Use the same «lb» and «ub» consistently across &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; so they all describe the same distribution.&lt;br /&gt;
&lt;br /&gt;
== Fitting the distribution to your data ==&lt;br /&gt;
&lt;br /&gt;
These two functions are used '''before''' constructing the distribution, to estimate the centering parameter and fit the coefficients.&lt;br /&gt;
&lt;br /&gt;
=== QFlexEstimateGamma( p, q, I ) ===&lt;br /&gt;
&lt;br /&gt;
Estimates the QFlex centering parameter «gamma» from assessed probability-quantile pairs («p», «q») indexed by «I». It estimates Q(0.1), Q(0.5), and Q(0.9) from your assessed quantiles by interpolation, computes the Kelly skewness index ''SI'', and returns gamma = 0.5 &amp;amp;times; (1 &amp;amp;minus; ''SI''), clipped to the open interval (0, 1).&lt;br /&gt;
&lt;br /&gt;
* «p»: The assessed probabilities, each in (0, 1), indexed by «I».&lt;br /&gt;
* «q»: The corresponding assessed quantile values, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
&lt;br /&gt;
Returns gamma = 0.5 for a symmetric assessment with no skew (0.45 in the exactly symmetric case, matching the paper's convention), a value greater than 0.5 for right-skewed assessments, and less than 0.5 for left-skewed ones. If fewer than three points are supplied, it returns 0.5.&lt;br /&gt;
&lt;br /&gt;
''Why «gamma» matters:'' it centers the centered-uniform basis terms. Choosing «gamma» from the assessed skewness (rather than always 0.5) keeps the fit well-conditioned — important especially when your assessed probabilities are symmetric about 0.5.&lt;br /&gt;
&lt;br /&gt;
=== QFlexFit( p, q, I, K, ''gamma, numTerms'' ) ===&lt;br /&gt;
&lt;br /&gt;
Fits the QFlex coefficient vector «a» (indexed by «K») to your assessed pairs («p», «q») by constrained least squares: it minimizes squared quantile error subject to the monotonicity constraints (tail-coefficient nonnegativity and the tail-center magnitude bound) from the paper, so the fitted distribution is '''valid by construction'''. '''Requires the [[Analytica Optimizer]] edition''' (the fit is a QP).&lt;br /&gt;
&lt;br /&gt;
* «p», «q»: The assessed probabilities and quantiles, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
* «K»: The coefficient [[Index]]; its length sets the maximum number of terms.&lt;br /&gt;
* «gamma»: (Optional): The centering parameter. If omitted, &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; estimates it internally via &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;. '''Best practice:''' compute «gamma» once with &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt; and pass it explicitly, so the same value is used for both fitting and evaluation.&lt;br /&gt;
* «numTerms»: (Optional): How many terms (&amp;amp;le; &amp;lt;code&amp;gt;IndexLength(K)&amp;lt;/code&amp;gt;) to actually fit. If omitted, all of «K» is used. If «numTerms» is less than the length of «K», the result is still indexed by «K» and is &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in the positions beyond «numTerms».&lt;br /&gt;
&lt;br /&gt;
'''Returns''' the coefficient vector «a» indexed by «K» (with &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in any unused positions). Pass this vector, with the same «K» and «gamma», to &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Analytic distribution functions ==&lt;br /&gt;
&lt;br /&gt;
These functions evaluate the fitted distribution analytically at a point (or an array of points), without sampling. They all take the fitted coefficient vector «a» indexed by «K», the centering parameter «gamma», and the same optional bounds «lb»/«ub» described under [[#QFlex( a, K, gamma, lb, ub )|QFlex]].&lt;br /&gt;
&lt;br /&gt;
=== CumQFlexInv( p, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''inverse cumulative (quantile) function''': returns the value «x» such that P(X &amp;amp;le; «x») = «p». Evaluate it at a probability «p» (or an array of probabilities) to read quantiles off the fitted distribution. This is the closed-form construction; &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; simply calls it with a uniform random «p».&lt;br /&gt;
&lt;br /&gt;
* «p»: A probability in [0, 1] (or an array of them).&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; returns the fitted 90th percentile.&lt;br /&gt;
&lt;br /&gt;
=== CumQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''cumulative distribution function''': returns P(X &amp;amp;le; «x») for a value «x». It is computed by numerically inverting the quantile function (bisection), giving the analytic CDF at a point, independent of sampling.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the CDF.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlex( 0, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DensQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''probability density function''' f(«x»): returns the density at a value «x», using the quantile-density relationship (no sampling required). This is convenient for plotting a smooth PDF curve over a grid of «x» values.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the density.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;DensQFlex( Plot_x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note on bounds:''' An upper bound must be supplied together with a lower bound. Specifying «ub» without «lb» is not supported, and the analytic CDF/PDF return &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in that case. For an upper-bounded quantity, use the bounded [«lb», «ub»] form.&lt;br /&gt;
&lt;br /&gt;
== The demo model ==&lt;br /&gt;
&lt;br /&gt;
The demo model &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; provides an interactive playground:&lt;br /&gt;
* Editable assessed quantiles for several example data sets (a symmetric logistic, a right-skewed lognormal, a heavy-tailed Student-''t'', and two bimodal shapes), selectable individually.&lt;br /&gt;
* A number-of-terms control to explore how flexibility changes the fit.&lt;br /&gt;
* Live graphs of the fitted inverse CDF, CDF, and PDF, built from &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A QA-tests module with analytically tractable checks (for example, the coefficient vector «a» = [0, 1, 1] reproduces the standard logistic quantile), useful as worked sanity checks.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Keelin (MetaLog) distribution]] &amp;amp;mdash; a related quantile-parameterized distribution.&lt;br /&gt;
* [[UncertainLMH]] &amp;amp;mdash; simpler option when you have only a low-medium-high (e.g. 10-50-90) assessment.&lt;br /&gt;
* [[Analytica Optimizer]] &amp;amp;mdash; the edition required for fitting.&lt;br /&gt;
* [[Distribution Densities Library]]&lt;br /&gt;
* [[Probability Distributions]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64004</id>
		<title>QFlex distribution</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=QFlex_distribution&amp;diff=64004"/>
		<updated>2026-06-23T23:18:57Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Create QFlex distribution page (downloadable library; requires Optimizer). Draft — placeholder download links pending.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Continuous distributions]]&lt;br /&gt;
[[category:Unbounded distributions]]&lt;br /&gt;
[[category:Bounded distributions]]&lt;br /&gt;
[[category:Semi-bounded distributions]]&lt;br /&gt;
[[category:Univariate distributions]]&lt;br /&gt;
[[category:Custom distributions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
''Provided by a downloadable add-in library (not a built-in distribution). Fitting requires the [[Analytica Optimizer]] edition.''&lt;br /&gt;
&lt;br /&gt;
== QFlex( a, ''K, gamma, lb, ub'' ) ==&lt;br /&gt;
&lt;br /&gt;
The ''QFlex distribution'' (&amp;quot;Quantile Flexibility&amp;quot;) is a flexible, quantile-parameterized distribution capable of fitting a wide variety of continuous shapes directly to a set of assessed quantiles — for example a 10-50-90 judgment, or a larger set of assessed percentiles. Use it when standard parametric distributions such as the [[Normal distribution|Normal]], [[Log-normal distribution|LogNormal]], or [[Beta distribution|Beta]] are too restrictive to match what you have assessed, and you want a single smooth distribution that passes through (or near) your elicited quantiles while remaining a valid probability distribution.&lt;br /&gt;
&lt;br /&gt;
You obtain the coefficient vector «a» by fitting it to your assessed quantiles with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; (see [[#How to use the library|How to use the library]] below). &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; then draws a sampled, uncertain value from the fitted distribution, much as you would use a built-in distribution like &amp;lt;code&amp;gt;Normal&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;LogNormal&amp;lt;/code&amp;gt;. Define a Chance variable as &amp;lt;code&amp;gt;QFlex(...)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
;Reference&lt;br /&gt;
:Bickel, J. Eric, Connor Colombe, and Benjamin D. Leibowicz. ''The QFlex Distribution.'' The University of Texas at Austin. '''(Under review for publication, June 2026.)'''&lt;br /&gt;
:''The QFlex distribution and the methods implemented in this library are described in this paper. Because the paper is currently in review, the citation details may change.''&lt;br /&gt;
&lt;br /&gt;
'''QFlex is not a built-in Analytica distribution.''' It is provided as a downloadable [[Libraries|library]] (see [[#Download and installation|Download and installation]]). Because the coefficient fit is solved as a quadratic program (QP), the [[Analytica Optimizer]] edition is required to fit a QFlex distribution to your data.&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
* «a»: The QFlex coefficient vector, indexed by «K». You normally obtain this from &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «K»: The coefficient [[Index]]. Its length is the maximum number of terms. Use, e.g., &amp;lt;code&amp;gt;K := 1..10&amp;lt;/code&amp;gt;. (A 1-term QFlex is not a valid distribution, so use at least 2; more terms give a more flexible fit.)&lt;br /&gt;
* «gamma»: (Optional, default 0.5): The centering parameter. Use the same «gamma» that you used when fitting «a». See &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;.&lt;br /&gt;
* «lb», «ub»: (Optional): The support bounds. Omit both for an '''unbounded''' distribution; supply «lb» only for a '''lower-bounded''' [«lb», ∞) distribution; supply both for a '''bounded''' [«lb», «ub»] distribution.&lt;br /&gt;
&lt;br /&gt;
== About the QFlex distribution ==&lt;br /&gt;
&lt;br /&gt;
Internally, QFlex builds the distribution's quantile function (the inverse CDF) as a weighted sum of simple, individually valid building blocks: powers of a right-tail exponential, a left-tail (reflected) exponential, and a centered-uniform term. Because every building block is itself a valid, strictly increasing quantile function, a QFlex fit can be kept '''monotone — a genuine probability distribution — by construction''', through simple conditions on its coefficients. This is its main practical advantage over some other flexible quantile-parameterized families such as the [[Keelin (MetaLog) distribution|Keelin (MetaLog)]] distribution, which can require after-the-fact numerical &amp;quot;repair&amp;quot; to restore monotonicity.&lt;br /&gt;
&lt;br /&gt;
Consider QFlex when:&lt;br /&gt;
* You have '''more assessed (or empirical) quantiles than a standard 2-3 parameter distribution can honor''', and you want the distribution to match them rather than only approximate their mean and spread.&lt;br /&gt;
* You want a '''smooth, valid continuous distribution''' (with an analytic CDF and PDF) rather than a discrete or purely empirical one.&lt;br /&gt;
* You need '''control over skewness and tail behavior''', or want to shape the left tail, right tail, and center somewhat independently.&lt;br /&gt;
* Your quantity is '''unbounded, lower-bounded, or bounded''' — QFlex supports all three.&lt;br /&gt;
&lt;br /&gt;
The number of terms (the length of «K») controls flexibility: more terms can match more assessed quantiles and more complex shapes. With «K» terms you can interpolate up to «K» probability-quantile pairs; with more assessed pairs than terms, the fit is a constrained least-squares fit. You do '''not''' need to work through the paper's mathematics to use the library — the functions encapsulate the fitting and the analytic details for practical model building.&lt;br /&gt;
&lt;br /&gt;
== Download and installation ==&lt;br /&gt;
&lt;br /&gt;
QFlex is distributed as an Analytica library plus a demonstration model, both plain &amp;lt;code&amp;gt;.ana&amp;lt;/code&amp;gt; files:&lt;br /&gt;
* '''Library:''' &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; '''[download link to be added]'''&lt;br /&gt;
* '''Demo model:''' &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; &amp;amp;mdash; '''[download link to be added]'''&lt;br /&gt;
&lt;br /&gt;
To use the library in your own model, open your model and choose '''File &amp;amp;rarr; Add Library...''', select &amp;lt;code&amp;gt;QFlex distribution library.ana&amp;lt;/code&amp;gt;, and link it. The library's functions then become available in your model. The demo model already includes the library and shows the full workflow.&lt;br /&gt;
&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
* '''[[Analytica Optimizer]] edition.''' The fitting function &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; solves a quadratic program, which requires Optimizer. (Once you have a fitted coefficient vector, the remaining functions — &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; — are ordinary evaluations and do not themselves require Optimizer; but in normal use you fit with &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt;, so Optimizer is required.)&lt;br /&gt;
* Analytica 7.x or later is recommended.&lt;br /&gt;
&lt;br /&gt;
== How to use the library ==&lt;br /&gt;
&lt;br /&gt;
The workflow has three steps:&lt;br /&gt;
&lt;br /&gt;
# '''Compute the centering parameter «gamma».''' Use &amp;lt;code&amp;gt;QFlexEstimateGamma( p, q, I )&amp;lt;/code&amp;gt; on your assessed probability-quantile pairs, or specify a «gamma» yourself if you have a preferred value. Keep that «gamma» and pass the '''same''' value to the later functions.&lt;br /&gt;
# '''Fit the coefficient vector «a».''' Use &amp;lt;code&amp;gt;QFlexFit( p, q, I, K, gamma, numTerms )&amp;lt;/code&amp;gt; with your probabilities «p», quantiles «q», the assessment index «I», and the coefficient index «K». ''(This step requires the Optimizer edition.)''&lt;br /&gt;
# '''Use the fitted distribution.''' Call &amp;lt;code&amp;gt;QFlex( a, K, gamma, lb, ub )&amp;lt;/code&amp;gt; to construct the uncertain quantity, or use &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; for the inverse CDF, CDF, and density at specific points. Use the '''same «gamma» and «K»''' that you used when fitting.&lt;br /&gt;
&lt;br /&gt;
Because «gamma» is an explicit parameter to the QFlex functions, it is best to compute or choose «gamma» once and then pass that same value consistently to the fitting and evaluation functions.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Fit to assessed quantiles ===&lt;br /&gt;
&lt;br /&gt;
Suppose you have assessed ten quantiles of an uncertain quantity. Define an index of the assessed probabilities, the assessed quantile values, and a coefficient index:&lt;br /&gt;
&lt;br /&gt;
:Index Quantile_probability := &amp;lt;code&amp;gt;[0.01, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99, 0.999]&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable Assessed_quantiles := &amp;lt;code&amp;gt;Table( Quantile_probability )( ... )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''(your ten assessed quantile values)''&lt;br /&gt;
:Index K_terms := &amp;lt;code&amp;gt;1..10&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then carry out the three steps:&lt;br /&gt;
&lt;br /&gt;
:Variable Gamma_to_use := &amp;lt;code&amp;gt;QFlexEstimateGamma( Quantile_probability, Assessed_quantiles, Quantile_probability )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Variable QFlex_coefficients := &amp;lt;code&amp;gt;QFlexFit( Quantile_probability, Assessed_quantiles, Quantile_probability, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
:Chance Fitted_distribution := &amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now &amp;lt;code&amp;gt;Fitted_distribution&amp;lt;/code&amp;gt; is an uncertain quantity you can use anywhere in your model. You can also read the fitted distribution analytically at specific points:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the fitted 90th percentile''&lt;br /&gt;
:&amp;lt;code&amp;gt;CumQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the CDF, P(X &amp;amp;le; x)''&lt;br /&gt;
:&amp;lt;code&amp;gt;DensQFlex( x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''the density (PDF) at x''&lt;br /&gt;
&lt;br /&gt;
=== Bounded and semi-bounded fits ===&lt;br /&gt;
&lt;br /&gt;
To fit a distribution known to be non-negative (for example, a cost or a physical quantity), pass a lower bound to the construction and evaluation functions:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''lower-bounded at 0''&lt;br /&gt;
:&amp;lt;code&amp;gt;QFlex( QFlex_coefficients, K_terms, Gamma_to_use, lb: 0, ub: 100 )&amp;lt;/code&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;''bounded on [0, 100]''&lt;br /&gt;
&lt;br /&gt;
Use the same «lb» and «ub» consistently across &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt; so they all describe the same distribution.&lt;br /&gt;
&lt;br /&gt;
== Fitting the distribution to your data ==&lt;br /&gt;
&lt;br /&gt;
These two functions are used '''before''' constructing the distribution, to estimate the centering parameter and fit the coefficients.&lt;br /&gt;
&lt;br /&gt;
=== QFlexEstimateGamma( p, q, I ) ===&lt;br /&gt;
&lt;br /&gt;
Estimates the QFlex centering parameter «gamma» from assessed probability-quantile pairs («p», «q») indexed by «I». It estimates Q(0.1), Q(0.5), and Q(0.9) from your assessed quantiles by interpolation, computes the Kelly skewness index ''SI'', and returns gamma = 0.5 &amp;amp;times; (1 &amp;amp;minus; ''SI''), clipped to the open interval (0, 1).&lt;br /&gt;
&lt;br /&gt;
* «p»: The assessed probabilities, each in (0, 1), indexed by «I».&lt;br /&gt;
* «q»: The corresponding assessed quantile values, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
&lt;br /&gt;
Returns gamma = 0.5 for a symmetric assessment with no skew (0.45 in the exactly symmetric case, matching the paper's convention), a value greater than 0.5 for right-skewed assessments, and less than 0.5 for left-skewed ones. If fewer than three points are supplied, it returns 0.5.&lt;br /&gt;
&lt;br /&gt;
''Why «gamma» matters:'' it centers the centered-uniform basis terms. Choosing «gamma» from the assessed skewness (rather than always 0.5) keeps the fit well-conditioned — important especially when your assessed probabilities are symmetric about 0.5.&lt;br /&gt;
&lt;br /&gt;
=== QFlexFit( p, q, I, K, ''gamma, numTerms'' ) ===&lt;br /&gt;
&lt;br /&gt;
Fits the QFlex coefficient vector «a» (indexed by «K») to your assessed pairs («p», «q») by constrained least squares: it minimizes squared quantile error subject to the monotonicity constraints (tail-coefficient nonnegativity and the tail-center magnitude bound) from the paper, so the fitted distribution is '''valid by construction'''. '''Requires the [[Analytica Optimizer]] edition''' (the fit is a QP).&lt;br /&gt;
&lt;br /&gt;
* «p», «q»: The assessed probabilities and quantiles, indexed by «I».&lt;br /&gt;
* «I»: The [[Index]] over the assessments.&lt;br /&gt;
* «K»: The coefficient [[Index]]; its length sets the maximum number of terms.&lt;br /&gt;
* «gamma»: (Optional): The centering parameter. If omitted, &amp;lt;code&amp;gt;QFlexFit&amp;lt;/code&amp;gt; estimates it internally via &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt;. '''Best practice:''' compute «gamma» once with &amp;lt;code&amp;gt;QFlexEstimateGamma&amp;lt;/code&amp;gt; and pass it explicitly, so the same value is used for both fitting and evaluation.&lt;br /&gt;
* «numTerms»: (Optional): How many terms (&amp;amp;le; &amp;lt;code&amp;gt;IndexLength(K)&amp;lt;/code&amp;gt;) to actually fit. If omitted, all of «K» is used. If «numTerms» is less than the length of «K», the result is still indexed by «K» and is &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in the positions beyond «numTerms».&lt;br /&gt;
&lt;br /&gt;
'''Returns''' the coefficient vector «a» indexed by «K» (with &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in any unused positions). Pass this vector, with the same «K» and «gamma», to &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Analytic distribution functions ==&lt;br /&gt;
&lt;br /&gt;
These functions evaluate the fitted distribution analytically at a point (or an array of points), without sampling. They all take the fitted coefficient vector «a» indexed by «K», the centering parameter «gamma», and the same optional bounds «lb»/«ub» described under [[#QFlex( a, K, gamma, lb, ub )|QFlex]].&lt;br /&gt;
&lt;br /&gt;
=== CumQFlexInv( p, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''inverse cumulative (quantile) function''': returns the value «x» such that P(X &amp;amp;le; «x») = «p». Evaluate it at a probability «p» (or an array of probabilities) to read quantiles off the fitted distribution. This is the closed-form construction; &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt; simply calls it with a uniform random «p».&lt;br /&gt;
&lt;br /&gt;
* «p»: A probability in [0, 1] (or an array of them).&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlexInv( 0.9, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt; returns the fitted 90th percentile.&lt;br /&gt;
&lt;br /&gt;
=== CumQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''cumulative distribution function''': returns P(X &amp;amp;le; «x») for a value «x». It is computed by numerically inverting the quantile function (bisection), giving the analytic CDF at a point, independent of sampling.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the CDF.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;CumQFlex( 0, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== DensQFlex( x, a, K, ''gamma, lb, ub'' ) ===&lt;br /&gt;
&lt;br /&gt;
The analytic '''probability density function''' f(«x»): returns the density at a value «x», using the quantile-density relationship (no sampling required). This is convenient for plotting a smooth PDF curve over a grid of «x» values.&lt;br /&gt;
&lt;br /&gt;
* «x»: The value (or array of values) at which to evaluate the density.&lt;br /&gt;
* «a», «K», «gamma», «lb», «ub»: As for &amp;lt;code&amp;gt;QFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example:''' &amp;lt;code&amp;gt;DensQFlex( Plot_x, QFlex_coefficients, K_terms, Gamma_to_use )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note on bounds:''' An upper bound must be supplied together with a lower bound. Specifying «ub» without «lb» is not supported, and the analytic CDF/PDF return &amp;lt;code&amp;gt;Null&amp;lt;/code&amp;gt; in that case. For an upper-bounded quantity, use the bounded [«lb», «ub»] form.&lt;br /&gt;
&lt;br /&gt;
== The demo model ==&lt;br /&gt;
&lt;br /&gt;
The demo model &amp;lt;code&amp;gt;Demo of QFlex distribution.ana&amp;lt;/code&amp;gt; provides an interactive playground:&lt;br /&gt;
* Editable assessed quantiles for several example data sets (a symmetric logistic, a right-skewed lognormal, a heavy-tailed Student-''t'', and two bimodal shapes), selectable individually.&lt;br /&gt;
* A number-of-terms control to explore how flexibility changes the fit.&lt;br /&gt;
* Live graphs of the fitted inverse CDF, CDF, and PDF, built from &amp;lt;code&amp;gt;CumQFlexInv&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CumQFlex&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DensQFlex&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A QA-tests module with analytically tractable checks (for example, the coefficient vector «a» = [0, 1, 1] reproduces the standard logistic quantile), useful as worked sanity checks.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Keelin (MetaLog) distribution]] &amp;amp;mdash; a related quantile-parameterized distribution.&lt;br /&gt;
* [[UncertainLMH]] &amp;amp;mdash; simpler option when you have only a low-medium-high (e.g. 10-50-90) assessment.&lt;br /&gt;
* [[Analytica Optimizer]] &amp;amp;mdash; the edition required for fitting.&lt;br /&gt;
* [[Distribution Densities Library]]&lt;br /&gt;
* [[Probability Distributions]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63997</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63997"/>
		<updated>2026-06-22T18:23:02Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Misc. User Interface */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page lists new features in release 7.1, which is currently in early [[Beta Tester Page|Beta Testing]].  If have have an active subscription license, we encourage you to try it out from the [[Beta Tester Page]].&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
* There is a new option, '''Use as default arrow style''', on the right-mouse context menu for an influence diagram arrow. This sets the global arrow style default to match the selected arrow.&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
* Added a syntax construct for [[Namespaces#Scoped_namespace_inclusion:_Using|Scoped namespace inclusion]] to bring a namespace into scope for only a localized expression or lexical block.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63996</id>
		<title>Arrow bends, curves, and styles</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63996"/>
		<updated>2026-06-22T18:21:39Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Arrow menu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;New to [[What's new in Analytica 6.0?|Analytica 6.0]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
You can modify Influence Arrows to have multiple line segments or curves -- very handy when you want to avoid arrows crossing other arrows or nodes. You can also set an arrow's  thickness, linestyle, colors, and more.&lt;br /&gt;
&lt;br /&gt;
== Bends and Curves ==&lt;br /&gt;
&lt;br /&gt;
Here's how to add segments or spline curves to an influence arrow in Edit mode:&lt;br /&gt;
* Click a straight arrow to select it. It will show a square and round handles in the middle of the arrow.&lt;br /&gt;
* To bend the arrow into two straight line segments, drag the square handle.&lt;br /&gt;
* To add a curve to the arrow, drag the round handle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Example with curved colored styles arrows.png|400px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To modify a segmented or curved arrow, click the arrow to select it and then:&lt;br /&gt;
* To move the waypoints (the dark circles or squares), just drag them.&lt;br /&gt;
* To add another lines or curve, drag a new midpoint (open circle or square). &lt;br /&gt;
* You can also move the start point or end point of an arrow where it meets a node border. Simply drag the point along the border.&lt;br /&gt;
&lt;br /&gt;
== Arrow menu ==&lt;br /&gt;
&lt;br /&gt;
Use the arrow menu to further modify the arrow styles.&lt;br /&gt;
* Click an arrow to select it. &lt;br /&gt;
* Shift-click on additional arrow(s) if you want to select several.&lt;br /&gt;
* Right-click a selected arrow to show the arrow context menu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Arrow menu.png|500px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
* Then select:&lt;br /&gt;
** '''Curved''' to toggle between curved and straight segments.&lt;br /&gt;
** '''Remove way point''' to remove a segment.&lt;br /&gt;
** '''Remove all way points''' to restore a simple straight arrow.&lt;br /&gt;
** '''Dash style''' and then select solid, dashes, dots, dash-dot, or Dash-dot-dot.&lt;br /&gt;
** '''Double line''' to show the arrow as two lines.&lt;br /&gt;
** '''Thickness''' and then select a number to make the arrow thicker or thinner.&lt;br /&gt;
** '''Show color palette''' to show the [[Color palette]]. Click a color from the palette to color the selected arrow(s).{{Release|1=7.1|2=|3=&lt;br /&gt;
** '''Use as default arrow style''' (''new in [[Analytica 7.1]]'') to set the global default arrow styles to match the style for the selected arrow.}}&lt;br /&gt;
&amp;lt;!-- * Change either end cap (no anchor, an arrow, square, diamond or circle).--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show or hide arrows ===&lt;br /&gt;
&lt;br /&gt;
You can use the [[Diagram Style dialog]] for each Diagram (Module) to control whether to show arrows to and from indexes and functions (off by default) or modules (on by default). You can use the [[Node Style dialog]] for one or more selected nodes to control whether to show arrows from all its inputs or to all its outputs.  You can use the Arrow menu above to show or hide individual arrows:&lt;br /&gt;
&lt;br /&gt;
To hide an arrow, &lt;br /&gt;
* Click the arrow to select it&lt;br /&gt;
* Right-click to show the Arrow menu. &lt;br /&gt;
* Select '''Hide arrow'''&lt;br /&gt;
&lt;br /&gt;
To show a hidden arrow, &lt;br /&gt;
* You'll need to click around where you think it might be until you manage to select it.&lt;br /&gt;
* Right click to show the Arrow menu&lt;br /&gt;
* Select '''Show arrow''' to show the hidden arrow&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Analytica's default rules for when to show arrows typically depicts a dependency only once in a given diagram. For example, if you have alias nodes in the same diagram as the original variables, a redundant arrow does not appear between the aliases. It also hides arrows involving Index and Function objects when the Diagram Style preferences have arrows between functions and indexes turned off. You can now show an individual arrow that would not normally be shown as a result of these rules by drawing the arrow between the two objects (e.g., between the 2 alias nodes).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples==&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:System dynamics diagram with curved arrows.png|600px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; An influence diagram using Systems Dynamics notation for a software business. All nodes have their borders hidden, except for the stock nodes (rectangles using Decisions). The flows to and between stocks use the double arrow style.  The cloud (source or sink for stock flows in Systems Dynamics is an image pasted into a node. So is the &amp;quot;valve&amp;quot; image that controls stock flows.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Influence diagram with curved arrows for supply chain model.png|400px]]&lt;br /&gt;
&lt;br /&gt;
An influence diagram for a supply chain model for a beer brewery.&lt;br /&gt;
Curved arrows show influences that go in both directions between modules.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Draw arrows]]&lt;br /&gt;
* [[Draw arrows between modules]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63995</id>
		<title>Arrow bends, curves, and styles</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63995"/>
		<updated>2026-06-22T18:21:17Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Arrow menu */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;New to [[What's new in Analytica 6.0?|Analytica 6.0]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
You can modify Influence Arrows to have multiple line segments or curves -- very handy when you want to avoid arrows crossing other arrows or nodes. You can also set an arrow's  thickness, linestyle, colors, and more.&lt;br /&gt;
&lt;br /&gt;
== Bends and Curves ==&lt;br /&gt;
&lt;br /&gt;
Here's how to add segments or spline curves to an influence arrow in Edit mode:&lt;br /&gt;
* Click a straight arrow to select it. It will show a square and round handles in the middle of the arrow.&lt;br /&gt;
* To bend the arrow into two straight line segments, drag the square handle.&lt;br /&gt;
* To add a curve to the arrow, drag the round handle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Example with curved colored styles arrows.png|400px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To modify a segmented or curved arrow, click the arrow to select it and then:&lt;br /&gt;
* To move the waypoints (the dark circles or squares), just drag them.&lt;br /&gt;
* To add another lines or curve, drag a new midpoint (open circle or square). &lt;br /&gt;
* You can also move the start point or end point of an arrow where it meets a node border. Simply drag the point along the border.&lt;br /&gt;
&lt;br /&gt;
== Arrow menu ==&lt;br /&gt;
&lt;br /&gt;
Use the arrow menu to further modify the arrow styles.&lt;br /&gt;
* Click an arrow to select it. &lt;br /&gt;
* Shift-click on additional arrow(s) if you want to select several.&lt;br /&gt;
* Right-click a selected arrow to show the arrow context menu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Arrow menu.png|500px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
* Then select:&lt;br /&gt;
** '''Curved''' to toggle between curved and straight segments.&lt;br /&gt;
** '''Remove way point''' to remove a segment.&lt;br /&gt;
** '''Remove all way points''' to restore a simple straight arrow.&lt;br /&gt;
** '''Dash style''' and then select solid, dashes, dots, dash-dot, or Dash-dot-dot.&lt;br /&gt;
** '''Double line''' to show the arrow as two lines.&lt;br /&gt;
** '''Thickness''' and then select a number to make the arrow thicker or thinner.&lt;br /&gt;
** '''Show color palette''' (''new in [[Analytica 7.1]]'') to show the [[Color palette]]. Click a color from the palette to color the selected arrow(s).{{Release|1=7.1|2=|3=&lt;br /&gt;
** '''Use as default arrow style''' to set the global default arrow styles to match the style for the selected arrow.}}&lt;br /&gt;
&amp;lt;!-- * Change either end cap (no anchor, an arrow, square, diamond or circle).--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show or hide arrows ===&lt;br /&gt;
&lt;br /&gt;
You can use the [[Diagram Style dialog]] for each Diagram (Module) to control whether to show arrows to and from indexes and functions (off by default) or modules (on by default). You can use the [[Node Style dialog]] for one or more selected nodes to control whether to show arrows from all its inputs or to all its outputs.  You can use the Arrow menu above to show or hide individual arrows:&lt;br /&gt;
&lt;br /&gt;
To hide an arrow, &lt;br /&gt;
* Click the arrow to select it&lt;br /&gt;
* Right-click to show the Arrow menu. &lt;br /&gt;
* Select '''Hide arrow'''&lt;br /&gt;
&lt;br /&gt;
To show a hidden arrow, &lt;br /&gt;
* You'll need to click around where you think it might be until you manage to select it.&lt;br /&gt;
* Right click to show the Arrow menu&lt;br /&gt;
* Select '''Show arrow''' to show the hidden arrow&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Analytica's default rules for when to show arrows typically depicts a dependency only once in a given diagram. For example, if you have alias nodes in the same diagram as the original variables, a redundant arrow does not appear between the aliases. It also hides arrows involving Index and Function objects when the Diagram Style preferences have arrows between functions and indexes turned off. You can now show an individual arrow that would not normally be shown as a result of these rules by drawing the arrow between the two objects (e.g., between the 2 alias nodes).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples==&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:System dynamics diagram with curved arrows.png|600px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; An influence diagram using Systems Dynamics notation for a software business. All nodes have their borders hidden, except for the stock nodes (rectangles using Decisions). The flows to and between stocks use the double arrow style.  The cloud (source or sink for stock flows in Systems Dynamics is an image pasted into a node. So is the &amp;quot;valve&amp;quot; image that controls stock flows.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Influence diagram with curved arrows for supply chain model.png|400px]]&lt;br /&gt;
&lt;br /&gt;
An influence diagram for a supply chain model for a beer brewery.&lt;br /&gt;
Curved arrows show influences that go in both directions between modules.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Draw arrows]]&lt;br /&gt;
* [[Draw arrows between modules]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63994</id>
		<title>Arrow bends, curves, and styles</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63994"/>
		<updated>2026-06-22T18:20:32Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Arrow menu */ ER 22257 -- New &amp;quot;Use as default arrow style&amp;quot; option on context menu&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;New to [[What's new in Analytica 6.0?|Analytica 6.0]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
You can modify Influence Arrows to have multiple line segments or curves -- very handy when you want to avoid arrows crossing other arrows or nodes. You can also set an arrow's  thickness, linestyle, colors, and more.&lt;br /&gt;
&lt;br /&gt;
== Bends and Curves ==&lt;br /&gt;
&lt;br /&gt;
Here's how to add segments or spline curves to an influence arrow in Edit mode:&lt;br /&gt;
* Click a straight arrow to select it. It will show a square and round handles in the middle of the arrow.&lt;br /&gt;
* To bend the arrow into two straight line segments, drag the square handle.&lt;br /&gt;
* To add a curve to the arrow, drag the round handle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Example with curved colored styles arrows.png|400px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To modify a segmented or curved arrow, click the arrow to select it and then:&lt;br /&gt;
* To move the waypoints (the dark circles or squares), just drag them.&lt;br /&gt;
* To add another lines or curve, drag a new midpoint (open circle or square). &lt;br /&gt;
* You can also move the start point or end point of an arrow where it meets a node border. Simply drag the point along the border.&lt;br /&gt;
&lt;br /&gt;
== Arrow menu ==&lt;br /&gt;
&lt;br /&gt;
Use the arrow menu to further modify the arrow styles.&lt;br /&gt;
* Click an arrow to select it. &lt;br /&gt;
* Shift-click on additional arrow(s) if you want to select several.&lt;br /&gt;
* Right-click a selected arrow to show the arrow context menu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Arrow menu.png|500px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
* Then select:&lt;br /&gt;
** '''Curved''' to toggle between curved and straight segments.&lt;br /&gt;
** '''Remove way point''' to remove a segment.&lt;br /&gt;
** '''Remove all way points''' to restore a simple straight arrow.&lt;br /&gt;
** '''Dash style''' and then select solid, dashes, dots, dash-dot, or Dash-dot-dot.&lt;br /&gt;
** '''Double line''' to show the arrow as two lines.&lt;br /&gt;
** '''Thickness''' and then select a number to make the arrow thicker or thinner.&lt;br /&gt;
** '''Show color palette''' to show the [[Color palette]]. Click a color from the palette to color the selected arrow(s).&lt;br /&gt;
&amp;lt;!-- * Change either end cap (no anchor, an arrow, square, diamond or circle).--&amp;gt;{{Release|1=7.1|2=|3=&lt;br /&gt;
** '''Use as default arrow style''' to set the global default arrow styles to match the style for the selected arrow.}}&lt;br /&gt;
&lt;br /&gt;
=== Show or hide arrows ===&lt;br /&gt;
&lt;br /&gt;
You can use the [[Diagram Style dialog]] for each Diagram (Module) to control whether to show arrows to and from indexes and functions (off by default) or modules (on by default). You can use the [[Node Style dialog]] for one or more selected nodes to control whether to show arrows from all its inputs or to all its outputs.  You can use the Arrow menu above to show or hide individual arrows:&lt;br /&gt;
&lt;br /&gt;
To hide an arrow, &lt;br /&gt;
* Click the arrow to select it&lt;br /&gt;
* Right-click to show the Arrow menu. &lt;br /&gt;
* Select '''Hide arrow'''&lt;br /&gt;
&lt;br /&gt;
To show a hidden arrow, &lt;br /&gt;
* You'll need to click around where you think it might be until you manage to select it.&lt;br /&gt;
* Right click to show the Arrow menu&lt;br /&gt;
* Select '''Show arrow''' to show the hidden arrow&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Analytica's default rules for when to show arrows typically depicts a dependency only once in a given diagram. For example, if you have alias nodes in the same diagram as the original variables, a redundant arrow does not appear between the aliases. It also hides arrows involving Index and Function objects when the Diagram Style preferences have arrows between functions and indexes turned off. You can now show an individual arrow that would not normally be shown as a result of these rules by drawing the arrow between the two objects (e.g., between the 2 alias nodes).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples==&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:System dynamics diagram with curved arrows.png|600px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; An influence diagram using Systems Dynamics notation for a software business. All nodes have their borders hidden, except for the stock nodes (rectangles using Decisions). The flows to and between stocks use the double arrow style.  The cloud (source or sink for stock flows in Systems Dynamics is an image pasted into a node. So is the &amp;quot;valve&amp;quot; image that controls stock flows.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Influence diagram with curved arrows for supply chain model.png|400px]]&lt;br /&gt;
&lt;br /&gt;
An influence diagram for a supply chain model for a beer brewery.&lt;br /&gt;
Curved arrows show influences that go in both directions between modules.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Draw arrows]]&lt;br /&gt;
* [[Draw arrows between modules]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63993</id>
		<title>Arrow bends, curves, and styles</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Arrow_bends,_curves,_and_styles&amp;diff=63993"/>
		<updated>2026-06-22T18:17:17Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;New to [[What's new in Analytica 6.0?|Analytica 6.0]]&lt;br /&gt;
&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
You can modify Influence Arrows to have multiple line segments or curves -- very handy when you want to avoid arrows crossing other arrows or nodes. You can also set an arrow's  thickness, linestyle, colors, and more.&lt;br /&gt;
&lt;br /&gt;
== Bends and Curves ==&lt;br /&gt;
&lt;br /&gt;
Here's how to add segments or spline curves to an influence arrow in Edit mode:&lt;br /&gt;
* Click a straight arrow to select it. It will show a square and round handles in the middle of the arrow.&lt;br /&gt;
* To bend the arrow into two straight line segments, drag the square handle.&lt;br /&gt;
* To add a curve to the arrow, drag the round handle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Example with curved colored styles arrows.png|400px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To modify a segmented or curved arrow, click the arrow to select it and then:&lt;br /&gt;
* To move the waypoints (the dark circles or squares), just drag them.&lt;br /&gt;
* To add another lines or curve, drag a new midpoint (open circle or square). &lt;br /&gt;
* You can also move the start point or end point of an arrow where it meets a node border. Simply drag the point along the border.&lt;br /&gt;
&lt;br /&gt;
== Arrow menu ==&lt;br /&gt;
&lt;br /&gt;
Use the arrow menu to further modify the arrow styles.&lt;br /&gt;
* Click an arrow to select it. &lt;br /&gt;
* Shift-click on additional arrow(s) if you want to select several.&lt;br /&gt;
* Right-click a selected arrow to show the arrow context menu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Arrow menu.png|500px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
* Then select:&lt;br /&gt;
** '''Curved''' to toggle between curved and straight segments.&lt;br /&gt;
** '''Remove way point''' to remove a segment.&lt;br /&gt;
** '''Remove all way points''' to restore a simple straight arrow.&lt;br /&gt;
** '''Dash style''' and then select solid, dashes, dots, dash-dot, or Dash-dot-dot.&lt;br /&gt;
** '''Double line''' to show the arrow as two lines.&lt;br /&gt;
** '''Thickness''' and then select a number to make the arrow thicker or thinner.&lt;br /&gt;
** '''Show color palette''' to show the [[Color palette]]. Click a color from the palette to color the selected arrow(s).&lt;br /&gt;
&amp;lt;!-- * Change either end cap (no anchor, an arrow, square, diamond or circle).--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show or hide arrows ===&lt;br /&gt;
&lt;br /&gt;
You can use the [[Diagram Style dialog]] for each Diagram (Module) to control whether to show arrows to and from indexes and functions (off by default) or modules (on by default). You can use the [[Node Style dialog]] for one or more selected nodes to control whether to show arrows from all its inputs or to all its outputs.  You can use the Arrow menu above to show or hide individual arrows:&lt;br /&gt;
&lt;br /&gt;
To hide an arrow, &lt;br /&gt;
* Click the arrow to select it&lt;br /&gt;
* Right-click to show the Arrow menu. &lt;br /&gt;
* Select '''Hide arrow'''&lt;br /&gt;
&lt;br /&gt;
To show a hidden arrow, &lt;br /&gt;
* You'll need to click around where you think it might be until you manage to select it.&lt;br /&gt;
* Right click to show the Arrow menu&lt;br /&gt;
* Select '''Show arrow''' to show the hidden arrow&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Analytica's default rules for when to show arrows typically depicts a dependency only once in a given diagram. For example, if you have alias nodes in the same diagram as the original variables, a redundant arrow does not appear between the aliases. It also hides arrows involving Index and Function objects when the Diagram Style preferences have arrows between functions and indexes turned off. You can now show an individual arrow that would not normally be shown as a result of these rules by drawing the arrow between the two objects (e.g., between the 2 alias nodes).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Examples==&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:System dynamics diagram with curved arrows.png|600px]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; An influence diagram using Systems Dynamics notation for a software business. All nodes have their borders hidden, except for the stock nodes (rectangles using Decisions). The flows to and between stocks use the double arrow style.  The cloud (source or sink for stock flows in Systems Dynamics is an image pasted into a node. So is the &amp;quot;valve&amp;quot; image that controls stock flows.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;[[image:Influence diagram with curved arrows for supply chain model.png|400px]]&lt;br /&gt;
&lt;br /&gt;
An influence diagram for a supply chain model for a beer brewery.&lt;br /&gt;
Curved arrows show influences that go in both directions between modules.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* [[Draw arrows]]&lt;br /&gt;
* [[Draw arrows between modules]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=CumDist_-_Custom_continuous_distribution_using_cumulative_probabilities&amp;diff=63991</id>
		<title>CumDist - Custom continuous distribution using cumulative probabilities</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=CumDist_-_Custom_continuous_distribution_using_cumulative_probabilities&amp;diff=63991"/>
		<updated>2026-06-19T21:11:08Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: It accepts r_i when it is non-descending but not scrictly increasing.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Continuous distributions]]&lt;br /&gt;
[[category:Bounded distributions]]&lt;br /&gt;
[[category:Custom distributions]]&lt;br /&gt;
[[category:Univariate distributions]]&lt;br /&gt;
[[Category:Doc Status C]] &amp;lt;!-- For Lumina use, do not change --&amp;gt;&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;CumDist&amp;lt;/code&amp;gt; functions are used to specify an arbitrarily shaped distribution by specifying points (pi,ri) on the cumulative probability curve. &lt;br /&gt;
&lt;br /&gt;
== Functions ==&lt;br /&gt;
&lt;br /&gt;
For each function below, the shape is described by two arrays, «p_i» and «r_i», each indexed by index «&amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt;». These are points on the cumulative density (CDF) curve. «p_i» and «r_i» must be non-decreasing along «&amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt;».  The index «&amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt;» may be omitted when either «p_i» or «r_i» is itself an index.&lt;br /&gt;
&lt;br /&gt;
In addition, an optional boolean «smooth» parameter (defaults to true) causes the CDF to be smooth and the PDF to be continuous. When set to False, the CDF is piecewise linear, which implies the PDF is piecewise constant and discontinuous. &lt;br /&gt;
&lt;br /&gt;
; Naming convention note:&lt;br /&gt;
There is a convention that the Analytic functions use the names &amp;lt;code&amp;gt;Dens«Dist»()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Cum«Dist»()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Cum«Dist»Inv()&amp;lt;/code&amp;gt;, where «Dist» is the distribution function name. That convention is used with this function, but results in the repeated &amp;quot;CumCum&amp;quot; for two of the functions. Also, this convention is applied to the [[ProbDist]] distribution function also, so be careful not to confuse [[CumProbDist]] with [[CumDist]], etc.&lt;br /&gt;
&lt;br /&gt;
=== CumDist(p_i, r_i'', I, over, smooth'') ===&lt;br /&gt;
&lt;br /&gt;
The distribution function. Use this function to describe a quantity having the custom distribution described by («p_i», «r_i»). To specify  independent by identically distributed quantities along additional indexes, list those other indexes in the «over» parameter.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;div id=&amp;quot;DensCumDist&amp;quot;&amp;gt;DensCumDist(x, p_i, r_i'', I, smooth'')&amp;lt;/div&amp;gt; ===&lt;br /&gt;
''New to [[Analytica 5.2]]''&lt;br /&gt;
&lt;br /&gt;
Returns the probability density at each point in «x».&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;div id=&amp;quot;CumCumDist&amp;quot;&amp;gt;CumCumDist(x, p_i, r_i'', I, smooth'')&amp;lt;/div&amp;gt; ===&lt;br /&gt;
''New to [[Analytica 5.2]]''&lt;br /&gt;
&lt;br /&gt;
Returns the cumulative probability at «x» -- the probability that the quantity is less than or equal to «x».&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;div id=&amp;quot;CumCumDistInv&amp;quot;&amp;gt;CumCumDistInv(p, p_i, r_i'', I, smooth'')&amp;lt;/div&amp;gt; ===&lt;br /&gt;
''New to [[Analytica 5.2]]''&lt;br /&gt;
&lt;br /&gt;
The inverse cumulative probability. Returns the «p»&amp;lt;sup&amp;gt;th&amp;lt;/sup&amp;gt; fractile/quantile/percentile.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
* The analytic functions are new to [[Analytica 5.2]].&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[ProbDist]]&lt;br /&gt;
* [[Fractiles]]&lt;br /&gt;
* [[Cdf and Pdf Functions]]&lt;br /&gt;
* [[Custom continuous distributions]]&lt;br /&gt;
* [[Distribution Densities Library]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63988</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63988"/>
		<updated>2026-06-17T14:27:30Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page lists new features in release 7.1, which is currently in early [[Beta Tester Page|Beta Testing]].  If have have an active subscription license, we encourage you to try it out from the [[Beta Tester Page]].&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
* Added a syntax construct for [[Namespaces#Scoped_namespace_inclusion:_Using|Scoped namespace inclusion]] to bring a namespace into scope for only a localized expression or lexical block.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Analytica_7.1_beta_Release_Notes&amp;diff=63987</id>
		<title>Analytica 7.1 beta Release Notes</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Analytica_7.1_beta_Release_Notes&amp;diff=63987"/>
		<updated>2026-06-17T14:21:44Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Created page with &amp;quot;Category: Release notes  &amp;lt;&amp;lt; Beta Tester Page  For a list of 7.1 enhancements since the release of Analytica 7.0, see What's new in Analytica 7.1...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category: Release notes]]&lt;br /&gt;
&lt;br /&gt;
[[Beta Tester Page|&amp;lt;&amp;lt; Beta Tester Page]]&lt;br /&gt;
&lt;br /&gt;
For a list of 7.1 enhancements since the release of [[Analytica 7.0]], see [[What's new in Analytica 7.1?]].&lt;br /&gt;
&lt;br /&gt;
Substantial changes or fixes that have occurred since the previous beta build are listed on the individual pages below.&lt;br /&gt;
&lt;br /&gt;
== Notes for individual builds ==&lt;br /&gt;
&lt;br /&gt;
* Build 7.1.4.313: First public ''beta'' release. See [[What's new in Analytica 7.1?]].&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Beta_Tester_Page&amp;diff=63986</id>
		<title>Beta Tester Page</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Beta_Tester_Page&amp;diff=63986"/>
		<updated>2026-06-17T14:20:32Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; [[Category: Beta testing]]&lt;br /&gt;
{{#svarset:betarelease|7.1}}&lt;br /&gt;
{{#svarset:prevrelease|7.1}}&lt;br /&gt;
&lt;br /&gt;
We invite you to be a beta tester of [[Analytica {{#svarget:betarelease}}]] if you have Analytica {{#svarget:prevrelease}} installed on your computer with an active subscription. (Sorry, not [[Analytica Free Edition]] and not a legacy permanent license). A floating license subscription works.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;span style=&amp;quot;font-size: 20px;color:blue;&amp;quot;&amp;gt;We are no longer in beta testing.&amp;lt;/span&amp;gt;&lt;br /&gt;
The beta testing period for [[Analytica {{#svarget:prevrelease}}]] has ended and [[Analytica {{#svarget:betarelease}}]] is now the current release!  Please visit the [https://analytica.com/support-2/analytica-downloads/ Analytica Downloads] page to get the latest installer.--&amp;gt;&lt;br /&gt;
&amp;lt;!--The beta testing period for [[Analytica {{#svarget:betarelease}}]] will start very soon. Please check this page for updates.&lt;br /&gt;
&lt;br /&gt;
When the next release goes into beta testing, this page will be updated.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Why become a beta tester? ==&lt;br /&gt;
* Test drive the upcoming release {{#svarget:betarelease}} and start using its [[Analytica {{#svarget:betarelease}}|new features]] immediately.&lt;br /&gt;
* Participate in webinars on tips and guides on new features.&lt;br /&gt;
* Help improve the final release. &lt;br /&gt;
* Check that your models work in the new release. Find any issues while they can still be fixed, ensuring a seamless transition for you and your model users when this release becomes official.&lt;br /&gt;
== As a beta tester, we request that you ==&lt;br /&gt;
* Read [[What's new in Analytica {{#svarget:betarelease}}?]] for an overview of the new features.&lt;br /&gt;
* Sign up as a beta tester by filling in the form when you run the installer.&lt;br /&gt;
* Try out the new Analytica enhancements of interest to you.&lt;br /&gt;
* [[Beta_Tester_Page/Submitting_a_Bug_Report|Submit a bug report]]  if you find an issue&lt;br /&gt;
* Keep up-to-date with the latest beta build.  Analytica will show you an alert whenever there is a new build ready to install, about every 2 weeks.  We may also send you email reminders.   See [[Analytica {{#svarget:betarelease}} beta Release Notes| release notes]] for changes and bug fixes in each beta release.&lt;br /&gt;
* We encourage you to retain Analytica {{#svarget:prevrelease}} when you install Analytica {{#svarget:betarelease}}  beta. That lets you compare their behavior if you suspect a new bug.&lt;br /&gt;
&lt;br /&gt;
== How to start beta-testing ==&lt;br /&gt;
Download the installer for the latest beta build, release number 7.1.4.313, from:&lt;br /&gt;
* [https://downloads.analytica.com/ANA7.1/AnaSetup7_1_4_313.exe Analytica {{#svarget:betarelease}} installer]&lt;br /&gt;
* [https://downloads.analytica.com/ANA7.1/AnaSetup7_1_4_313.exe ADE  {{#svarget:betarelease}} installer]&lt;br /&gt;
These beta builds use your existing {{#svarget:prevrelease}} subscription license that is already on your computer. A separate beta license is not required.&lt;br /&gt;
&lt;br /&gt;
The installers for the current non-beta release can be downloaded directly from the [https://analytica.com/support-2/analytica-downloads/ Analytica Downloads] page.&lt;br /&gt;
&lt;br /&gt;
== Improve Analytica docs ==&lt;br /&gt;
&lt;br /&gt;
During the alpha and beta testing period, we are still updating these Analytica Docs to reflect new features. [[What's new in Analytica {{#svarget:betarelease}}?]] is the most complete listing of new features, and is also a work in progress. As we approach final release date, this information will be more complete.&lt;br /&gt;
&lt;br /&gt;
As an Analytica user, you are invited to contribute to the docs! Since it's on a wiki (using Mediawiki software, just like Wikipedia), you can add or edit any content.  If you find something unclear, incomplete, or just wrong, feel free to fix it yourself. Or add comments, asking someone else to.  And you are welcome to add tips or interesting examples.&lt;br /&gt;
&lt;br /&gt;
== Known issues ==&lt;br /&gt;
&lt;br /&gt;
If you find an issue, please let us know about it at &amp;lt;code&amp;gt;support@lumina.com&amp;lt;/code&amp;gt;. Please see [[/Submitting a Bug Report|Submitting a bug report]] for instructions on reporting bugs.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' We list only the most important issues here (ones that might impact your ability to use it, or which are likely to be found and reported multiple times). We maintain a comprehensive bug base in-house, which is not accessible outside of Lumina.&lt;br /&gt;
&lt;br /&gt;
== FAQs: Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
See [[Analytica User FAQs]] for frequently asked questions not specific to {{#svarget:betarelease}} or to beta testing.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63985</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63985"/>
		<updated>2026-06-17T14:17:20Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Start Beta Testing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!--Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This page lists new features in release 7.1, which is currently in [[Beta Tester Page|Beta Testing]] prior to final release.  If have have an active subscription license, we encourage you to try it out from the [[Beta Tester Page]].&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
* Added a syntax construct for [[Namespaces#Scoped_namespace_inclusion:_Using|Scoped namespace inclusion]] to bring a namespace into scope for only a localized expression or lexical block.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63984</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63984"/>
		<updated>2026-06-11T23:56:13Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Built-in functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
* Added a syntax construct for [[Namespaces#Scoped_namespace_inclusion:_Using|Scoped namespace inclusion]] to bring a namespace into scope for only a localized expression or lexical block.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63983</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63983"/>
		<updated>2026-06-11T23:51:56Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Assista */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper or translate a spreadsheet into an Analytica model.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63982</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63982"/>
		<updated>2026-06-11T23:49:16Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Assista */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
* You can personalize her tone, style, level of verbosity and provide her custom instructions. To do this, click on the icon in the top-left corner of the Assista window and select Personization...&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63980</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63980"/>
		<updated>2026-06-11T13:40:48Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Assista */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* Your sessions are automatically saved, keyed to your model, and you can resume a previous session for that model from a session selector dropdown in the UI.&lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63979</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63979"/>
		<updated>2026-06-11T13:38:57Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can add or drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx, *.xlsx, *.xlsm&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation. It also has a new optional «ignoreAtFirstWarning» parameter that can be used in conjunction, capturing the first warning text in that second return value, not showing the return value to the user, and ignoring additional warnings during the duration of the Evaluate call (enables Assista to see the warnings).&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Evaluate&amp;diff=63978</id>
		<title>Evaluate</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Evaluate&amp;diff=63978"/>
		<updated>2026-06-11T13:37:03Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: ER 22271: document the new ignoreAtFirstWarning parameter (7.1)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Evaluation Functions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
Evaluate(t) is a powerful, but rarely needed function. If t is text, it parses it as an Analytica expression and evaluates it. If t is a handle to a variable, it evaluates and returns its value.&lt;br /&gt;
== Evaluate(t) ==&lt;br /&gt;
&lt;br /&gt;
If parameter «t» is a [[Text values|text value]],  [[Evaluate]](«t») tries to parse «t» as an Analytica [[expression]] (as in the [[definition]] of a Variable), evaluates it, and returns the resulting [[value]]. For example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Evaluate('10 * 10') &amp;amp;rarr; 100&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If parameter «t» is a [[Handle]] to a variable, [[Evaluate]](«t») evaluates the variable and returns its value:&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 100&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](A)) &amp;amp;rarr; 100&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You can also use it to evaluate a function passed as an object or handle:&lt;br /&gt;
:&amp;lt;code&amp;gt;Function Add(a, b)  :=  a+b&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](Add), 2, 10) &amp;amp;rarr; 12&amp;lt;/code&amp;gt;&lt;br /&gt;
This can be useful when you  want to define a function that takes a function as a parameter and applies the function in its body. &lt;br /&gt;
See [[#Using Evaluate on a Function]] below.&lt;br /&gt;
&lt;br /&gt;
== Handling errors ==&lt;br /&gt;
As of [[Analytica 6.6]], when an error occurs during the parsing or evaluation of «t» ''and'' the call to [[Evaluate]] appears within a [[Try]], evaluation transfers to the «catch» expression of the [[Try]] without presenting any error message dialog to the user. But this isn't true when the only surrounding (possibly nested) [[Try]]s have «errorNum» filters that do not match the occurring error.&lt;br /&gt;
&lt;br /&gt;
If error is not caught by a [[Try]], then a parsing error silently returns [[Null]] and an evaluation error appears to the user like any other evaluation error, typically terminating the computation.&lt;br /&gt;
&lt;br /&gt;
In [[Analytica 6.5]] and earlier, parsing errors are not caught by a surrounding [[Try]] -- they return Null as if there were no surrounding [[Try]].&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
== Capturing console output ==&lt;br /&gt;
''New to [[Analytica 7.1]].''&lt;br /&gt;
&lt;br /&gt;
[[Evaluate]] can optionally return a second value containing the text of everything printed to the console while «t» is evaluated, such as the output of any [[ConsolePrint]]() calls. To request it, capture two return values:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] (result, consoleText) {{eq}} [[Evaluate]]('ConsolePrint(2 + 2)') Do consoleText&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here &amp;lt;code&amp;gt;result&amp;lt;/code&amp;gt; is the value of the evaluated expression (here &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;), and &amp;lt;code&amp;gt;consoleText&amp;lt;/code&amp;gt; is the captured console output (here the text &amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; followed by a newline). Capturing the output does not prevent it from also appearing in the typescript window as it normally does.&lt;br /&gt;
&lt;br /&gt;
The second value captures only output produced ''during'' this evaluation. If «t» refers to a variable whose value is already cached, the variable is not recomputed, so it produces no console output and the captured text is empty.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
== Limiting evaluation time ==&lt;br /&gt;
''New to [[Analytica 7.1]].''&lt;br /&gt;
&lt;br /&gt;
The optional «maxSeconds» parameter sets an approximate limit, in seconds, on how long the evaluation of «t» may run. «maxSeconds» may be fractional, so &amp;lt;code&amp;gt;maxSeconds: 0.1&amp;lt;/code&amp;gt; limits evaluation to roughly 100&amp;amp;nbsp;milliseconds. The default of &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; means no time limit.&lt;br /&gt;
&lt;br /&gt;
If the evaluation does not complete within «maxSeconds», it is aborted and [[Evaluate]] throws an error reading ''&amp;quot;Evaluate reached the maximum time limit of N seconds without completing.&amp;quot;'' Because this is an ordinary evaluation error, you can catch it with a surrounding [[Try]]:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Try]]( [[Evaluate]]('Sum(Sqrt(1..100M))', maxSeconds: 0.5), catch: 'Timed out' )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The timing is approximate -- evaluation stops the next time it checks for interruption -- so the limit adds no measurable overhead to normal evaluation. This makes «maxSeconds» well suited to probing how far a long-running evaluation gets within a time budget, rather than to enforcing a precise deadline.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
== Controlling warnings ==&lt;br /&gt;
''New to [[Analytica 7.1]].''&lt;br /&gt;
&lt;br /&gt;
Normally, a warning that occurs while «t» is being evaluated is shown to the user, just as it would be during any other evaluation. The optional «ignoreAtFirstWarning» parameter, when &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, silently does what pressing the ''Ignore warnings'' button would do when the first warning occurs: no warning dialog is shown, evaluation continues, and any further warnings during the same call are ignored entirely (so that, for example, a warning that occurs in every cell of a million-cell array does not repeat a million times).&lt;br /&gt;
&lt;br /&gt;
The text of the first warning still goes to the console output, so by also capturing the second return value (see [[#Capturing console output|Capturing console output]] above) the calling code receives the warning text as feedback:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] (result, consoleText) {{eq}} [[Evaluate]]('Sqrt(-1)', ignoreAtFirstWarning: true) Do consoleText&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here &amp;lt;code&amp;gt;result&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;NaN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;consoleText&amp;lt;/code&amp;gt; contains the text ''&amp;quot;Warning: Square root of a negative number.&amp;quot;'' No dialog interrupts the user.&lt;br /&gt;
&lt;br /&gt;
The suppression applies only for the duration of the [[Evaluate]] call -- the previous warning setting is restored when [[Evaluate]] returns, so the user still sees warnings from later evaluations unless they had already silenced them. This parameter is particularly useful when code (such as an AI agent) calls [[Evaluate]] and wants feedback about warnings without showing dialogs to the user.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Limitations of Evaluate(t) ==&lt;br /&gt;
&lt;br /&gt;
There are some subtleties and limitations to Evaluate(«t») when «t» is a text value.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=|2=6.5|3=If text «t» contains a  [[syntax]] error, [[Evaluate]](«t») gives no error message, and returns [[Null]].}}&lt;br /&gt;
&lt;br /&gt;
The context inside the  Evaluate parameter is global, not local. So:&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 100&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable B := ([[Local]] A := 0; [[Evaluate]]('A + 1'))&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;B &amp;amp;rarr; 101&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Variable &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; inside &amp;lt;code&amp;gt;Evaluate('A + 1')&amp;lt;/code&amp;gt; refers to the global &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, not the local &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; defined in &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;. More generally:&lt;br /&gt;
&lt;br /&gt;
* [[Evaluate]](t) creates its own context for [[Parsed Expressions|parsing]] «t» (at evaluation time), which is not the context of the expression in which the [[Evaluate]](t) appears  -- e.g., the definition of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; above.&lt;br /&gt;
* So, text «t» cannot refer to [[Local Values|local value]]s, [[index]]es, or [[function parameters]] defined in the context in which the [[Evaluate]](t) function appears.&lt;br /&gt;
* Text «t» may itself define local values and indexes, and refer to them, but these will not be available outside «t».&lt;br /&gt;
* If the text value of «t» refers to a global variable —e.g., &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; in the definition of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; above—these do not appear as Inputs of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;. &lt;br /&gt;
* More generally, Analytica cannot track the dependency of any variable name that appears inside the text. So, for example, any change to &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; will not cause automatic re-evaluation of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;:&lt;br /&gt;
:&amp;lt;code&amp;gt;A := 3&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;B := A + 1&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;C := Evaluate('A + 1')&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;A := 5&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; changes, Analytica will automatically ensure that &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is updated, but it has no way of knowing &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; should also be recomputed.&lt;br /&gt;
&lt;br /&gt;
The parameter «t» may itself be an expression that creates a text value to be evaluated by [[Evaluate]]. This text expression appears in the definition of &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; and is not subject to the above limitations, so, for example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable V :=([[Local]] x:= ’10’; [[Evaluate]](x &amp;amp; x))&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;V &amp;amp;rarr; 1010&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== When to Use ==&lt;br /&gt;
&lt;br /&gt;
The cases in which you should use [[Evaluate]] are rare.  You should be reluctant to use it due to the caveats listed in the previous section. Typical cases when it is useful include:&lt;br /&gt;
* Parsing simple expressions.&lt;br /&gt;
* (advanced) Use in [[Meta-Inference]] algorithms where you are manipulating handles to objects in your model.&lt;br /&gt;
* (rare) Cases where you really do wish to by-pass dependency maintenance.  You want it to compute something the first time the result is requested after the model is first loaded, but not update when parent values are changes.&lt;br /&gt;
&lt;br /&gt;
== Non-text Parameters ==&lt;br /&gt;
&lt;br /&gt;
A non-text value can also be passed to [[Evaluate]], which can be of use in some [[Meta-Inference]] applications.  You need to keep in mind that the parameter to evaluate is evaluated BEFORE the function itself gets it, so evaluating a non-text value is only meaningful when the evaluated parameter is itself something that can still be evaluated.  One instance of this that is often useful is the case of a [[handle]] an object.&lt;br /&gt;
&lt;br /&gt;
For example, suppose &lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 2  + 3&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable TheVar := [[Handle]](A)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the more general case, you might have a [[Meta-Inference]] algorithm that identifies a single variable object through some computation. Having identified the object, &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; now holds a handle to the object.  You then may want to access values or properties of the object pointed to by &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt;, rather than just values or properties of &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; itself.  Evaluate serves this purpose:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;TheVar &amp;amp;rarr; A   { A -- i.e., a handle to the object A }&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](TheVar) &amp;amp;rarr; 5  { evaluates A }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is worth nothing that an alternative method also exists for evaluating a [[handle]].  You can declare a [[LocalAlias]] set to the handle, and then use its identifier as if it were the identifier of the object.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[LocalAlias]] x := TheVar Do x &amp;amp;rarr; 5    { x is an alias for A, so &amp;quot;x&amp;quot; in the body is the value of A }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When accessing attributes of an object in a [[Meta-Inference]] algorithm, where your algorithm has a handle to an object (again, say it is in &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt;), you can access the attribute using e.g.,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Description Of Evaluate(TheVar) &amp;amp;rarr; &amp;quot;Description of A&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Description Of TheVar &amp;amp;rarr; &amp;quot;Description of TheVar&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(the result of using &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; alone is shown for comparison).&lt;br /&gt;
&lt;br /&gt;
== Using Evaluate on a Function ==&lt;br /&gt;
&lt;br /&gt;
Given a [[handle]] to a function object, you can use [[Evaluate]] to call the function.  If the function expects ''N'' parameters, you would provide ''N+1'' parameters to [[Evaluate]] -- the first parameter being the handle to the function, and the remaining parameters being the values passed to the function.  Example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] fn := [[If]] opt = 1 [[Then]] [[Handle]]([[Max]]) [[Else]] [[If]] opt = 2 [[Then]] [[Handle]]([[Min]]) [[Else]] [[Handle]]([[Sum]]);&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, A, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parameters to the function being called are always passed by position, i.e., you cannot use a named-parameter calling syntax as you might if you were calling the function directly.  &lt;br /&gt;
&lt;br /&gt;
If the function being called contains repeated (or variable number of) parameters, and you need to include a parameter that follows the [[repeated parameter]], then you must place brackets around the repeated parameters.  For example, &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt; Function Fu1(x; y: repeated; z: optional) := ...&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;amp;nbsp;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, 1, 2, 3, 4) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;Fu1(1, 2, 3, 4)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;[2, 3, 4]&amp;lt;/code&amp;gt; are values for &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; is omitted''&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, 1, [2, 3], 4) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;Fu1(1, 2, 3, y: 4)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;[2, 3]&amp;lt;/code&amp;gt; are values for &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; is 4''.&lt;br /&gt;
&lt;br /&gt;
However, there is a limitation that the first supplied parameter (i.e., the second parameter to [[Evaluate]]) cannot be placed inside brackets.  Likewise, you cannot pass an literal list by specifying the first parameter as a bracketed list.  This is because the repeated-parameter syntax applies equally to [[Evaluate]].  If you specify the first parameter to [[Evaluate]] in brackets, those become the parameters to the function, i.e.,:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](F), [1, 2, 3, 4]) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;F(1, 2, 3, 4)''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Several common built-in functions, including [[Sum]], [[Max]], and [[Min]], allow a variable number of indexes, so that you can use &amp;lt;code&amp;gt;[[Sum]](A, I, J, K)&amp;lt;/code&amp;gt; to sum over 3 dimensions in a single call.  These functions also have [[optional parameter]]s, such as «ignoreNonNumbers», so that if you need to specify these optional parameters, you will need to place brackets around the index(es), even if only one (or zero) index is specified.  For example, the following examples show how to to specify «ignoreNonNumbers» as true to [[Sum]], when summing over a single index, and when summing over the [[implicit dimension]]:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]]([[Sum]]), A, [I], true)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] x := [3, 2, 'a', 'b', 6] do [[Evaluate]]([[Handle]]([[Sum]]),  x, [], true)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that if you don't need to specify the optional «ignoreNonNumbers» parameter (or any parameters that follow the repeated index parameters), then it is more natural to omit the brackets:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]]([[Sum]]), A, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] x := [3, 2, 5, 3, 6] do [[Evaluate]]([[Handle]]([[Sum]]), x)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Release|6.5||&lt;br /&gt;
== Evaluating in a different namespace context ==&lt;br /&gt;
''New to [[Analytica 6.5]]''&lt;br /&gt;
&lt;br /&gt;
Suppose there are two variables that both have the identifier X, but which live in different [[Namespaces]]. Then&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]( &amp;quot;X+1&amp;quot; )&amp;lt;/code&amp;gt;&lt;br /&gt;
would differ depending on where it appears. By default it resolves the identifier &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; from the namespace of the object containing the expression. In some esoteric situations, you may need to interpret the expression from a different namespace context.  You can do this by first obtaining a handle to the other namespace module, or to any object inside that namespace, and passing that handle to the «nsContext» parameter.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]( &amp;quot;X+1&amp;quot;, nsContext: [[Handle]](&amp;quot;NS2&amp;quot;) )&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:2;-moz-column-count:2;-webkit-column-count:2&amp;quot;&amp;gt;&lt;br /&gt;
* [[EvaluateScript]]&lt;br /&gt;
* [[Proactive Evaluation]]&lt;br /&gt;
* [[Evaluation Modes]]&lt;br /&gt;
* [[Handle]]&lt;br /&gt;
* [[Expression Syntax]]&lt;br /&gt;
* [[Expression Assist]]&lt;br /&gt;
* [[Parsed Expressions]]&lt;br /&gt;
* [[Function calls and parameters]]&lt;br /&gt;
* [[Summary of Programming Constructs]]&lt;br /&gt;
* [[Procedural Programming]]&lt;br /&gt;
* [[Meta-Inference]]{{Release|6.5||&lt;br /&gt;
* [[Namespaces]]}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Error_Messages/49963&amp;diff=63977</id>
		<title>Error Messages/49963</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Error_Messages/49963&amp;diff=63977"/>
		<updated>2026-06-10T22:20:02Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Rewrap message lines so the pre block doesn't need a horizontal scrollbar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category: Error messages]]&lt;br /&gt;
&lt;br /&gt;
== Error message ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:white; border:white; margin-left: 1em; font-style:italic&amp;quot;&amp;gt;&lt;br /&gt;
The first word of «cmdLine» (--version) does not appear to name the&lt;br /&gt;
«program» being launched (C:\Python313\python.exe). The new process&lt;br /&gt;
receives «cmdLine» as its complete command line and treats the first&lt;br /&gt;
word as its own program name (argv[0]), not as an argument. Either&lt;br /&gt;
repeat the program name at the start of «cmdLine», e.g.&lt;br /&gt;
cmdLine: 'python --version', or omit «program» and pass the entire&lt;br /&gt;
command line in «cmdLine».&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
This warning (it is a warning, not an error — the process is still launched exactly as you specified) appears when you call [[RunConsoleProcess]] with both the «program» and «cmdLine» parameters, and the first word of «cmdLine» does not appear to name the executable given in «program». The example message above results from:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;RunConsoleProcess('C:\Python313\python.exe', '--version')&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This call looks reasonable, but it does not run &amp;lt;code&amp;gt;python --version&amp;lt;/code&amp;gt;. By Windows convention, a newly launched process receives a single command-line string, and the first word of that string is the program's own name (&amp;lt;code&amp;gt;argv[0]&amp;lt;/code&amp;gt; in C parlance); the real arguments begin at the second word. [[RunConsoleProcess]] passes «cmdLine» to the new process as its complete command line, so in this example python sees &amp;lt;code&amp;gt;--version&amp;lt;/code&amp;gt; as its own program name and concludes that it was given no arguments at all. Rather than printing its version, python behaves as if launched bare: it reads a script from standard input (the «stdIn» parameter — empty here), runs it, and exits. The net effect is that the call returns empty text, with no other indication of what went wrong.&lt;br /&gt;
&lt;br /&gt;
To fix the call, do either of the following:&lt;br /&gt;
&lt;br /&gt;
* Repeat the program name as the first word of «cmdLine». It does not have to be the full path — the bare name is enough:&lt;br /&gt;
*:&amp;lt;code&amp;gt;RunConsoleProcess('C:\Python313\python.exe', 'python --version')&amp;lt;/code&amp;gt;&lt;br /&gt;
* Or pass the entire command line as a single parameter, and let Analytica locate the executable (quote the path if it contains spaces):&lt;br /&gt;
*:&amp;lt;code&amp;gt;RunConsoleProcess('&amp;quot;C:\Python313\python.exe&amp;quot; --version')&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The check that triggers this warning is forgiving about form: the first word of «cmdLine» may be a bare name or a full path, quoted or unquoted, with or without the &amp;lt;code&amp;gt;.exe&amp;lt;/code&amp;gt; extension, in any letter case. The warning is issued only when, after reducing both sides to a bare program name, they still differ.&lt;br /&gt;
&lt;br /&gt;
In the rare case where the mismatch is deliberate — a few programs intentionally inspect &amp;lt;code&amp;gt;argv[0]&amp;lt;/code&amp;gt; and vary their behavior based on the name they were invoked under — you can simply ignore the warning, or suppress it like any other warning. The process is launched with exactly the «program» and «cmdLine» you gave.&lt;br /&gt;
&lt;br /&gt;
This warning was added in Analytica 7.1.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[RunConsoleProcess]]&lt;br /&gt;
* [[Error Messages/40335]] — ''RunConsoleProcess could not launch the indicated process''&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Error_Messages/49963&amp;diff=63976</id>
		<title>Error Messages/49963</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Error_Messages/49963&amp;diff=63976"/>
		<updated>2026-06-10T22:19:14Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: New page for warning 49963 (ER 22270): RunConsoleProcess cmdLine first word should repeat the program name (argv[0])&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category: Error messages]]&lt;br /&gt;
&lt;br /&gt;
== Error message ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:white; border:white; margin-left: 1em; font-style:italic&amp;quot;&amp;gt;&lt;br /&gt;
The first word of «cmdLine» (--version) does not appear to name the «program» being&lt;br /&gt;
launched (C:\Python313\python.exe). The new process receives «cmdLine» as its complete&lt;br /&gt;
command line and treats the first word as its own program name (argv[0]), not as an&lt;br /&gt;
argument. Either repeat the program name at the start of «cmdLine», e.g.&lt;br /&gt;
cmdLine: 'python --version', or omit «program» and pass the entire command line in «cmdLine».&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
This warning (it is a warning, not an error — the process is still launched exactly as you specified) appears when you call [[RunConsoleProcess]] with both the «program» and «cmdLine» parameters, and the first word of «cmdLine» does not appear to name the executable given in «program». The example message above results from:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;RunConsoleProcess('C:\Python313\python.exe', '--version')&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This call looks reasonable, but it does not run &amp;lt;code&amp;gt;python --version&amp;lt;/code&amp;gt;. By Windows convention, a newly launched process receives a single command-line string, and the first word of that string is the program's own name (&amp;lt;code&amp;gt;argv[0]&amp;lt;/code&amp;gt; in C parlance); the real arguments begin at the second word. [[RunConsoleProcess]] passes «cmdLine» to the new process as its complete command line, so in this example python sees &amp;lt;code&amp;gt;--version&amp;lt;/code&amp;gt; as its own program name and concludes that it was given no arguments at all. Rather than printing its version, python behaves as if launched bare: it reads a script from standard input (the «stdIn» parameter — empty here), runs it, and exits. The net effect is that the call returns empty text, with no other indication of what went wrong.&lt;br /&gt;
&lt;br /&gt;
To fix the call, do either of the following:&lt;br /&gt;
&lt;br /&gt;
* Repeat the program name as the first word of «cmdLine». It does not have to be the full path — the bare name is enough:&lt;br /&gt;
*:&amp;lt;code&amp;gt;RunConsoleProcess('C:\Python313\python.exe', 'python --version')&amp;lt;/code&amp;gt;&lt;br /&gt;
* Or pass the entire command line as a single parameter, and let Analytica locate the executable (quote the path if it contains spaces):&lt;br /&gt;
*:&amp;lt;code&amp;gt;RunConsoleProcess('&amp;quot;C:\Python313\python.exe&amp;quot; --version')&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The check that triggers this warning is forgiving about form: the first word of «cmdLine» may be a bare name or a full path, quoted or unquoted, with or without the &amp;lt;code&amp;gt;.exe&amp;lt;/code&amp;gt; extension, in any letter case. The warning is issued only when, after reducing both sides to a bare program name, they still differ.&lt;br /&gt;
&lt;br /&gt;
In the rare case where the mismatch is deliberate — a few programs intentionally inspect &amp;lt;code&amp;gt;argv[0]&amp;lt;/code&amp;gt; and vary their behavior based on the name they were invoked under — you can simply ignore the warning, or suppress it like any other warning. The process is launched with exactly the «program» and «cmdLine» you gave.&lt;br /&gt;
&lt;br /&gt;
This warning was added in Analytica 7.1.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
* [[RunConsoleProcess]]&lt;br /&gt;
* [[Error Messages/40335]] — ''RunConsoleProcess could not launch the indicated process''&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=GetProcessInfo&amp;diff=63975</id>
		<title>GetProcessInfo</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=GetProcessInfo&amp;diff=63975"/>
		<updated>2026-06-10T21:01:49Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Types of information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; [[Category:System Functions]]&lt;br /&gt;
[[Category: Memory management]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
[[GetProcessInfo]] can give you information about the current Analytica or [[ADE]] process, such as user name, computer, name, memory in use, number of processors available, number of objects in the model, and a whole lot more. from the Windows operating system,&lt;br /&gt;
&lt;br /&gt;
== Types of information  ==&lt;br /&gt;
&lt;br /&gt;
[[GetProcessInfo]] returns information about the current Analytica or [[ADE]] process from the Windows operating system, according to which of these texts you pass as the «item» parameter:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Process ID&amp;quot;&amp;lt;/code&amp;gt; -- returns the Process ID, or Pid, for the current process.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Thread ID&amp;quot;&amp;lt;/code&amp;gt; -- returns the Id of the Analytica/ADE thread.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Priority&amp;quot;&amp;lt;/code&amp;gt; -- returns the priority of the Analytica/ADE thread.  The following values are possible (defined by the Windows operating system):&lt;br /&gt;
::*&amp;lt;code&amp;gt;-15&amp;lt;/code&amp;gt; : Idle only&lt;br /&gt;
::*&amp;lt;code&amp;gt;-2&amp;lt;/code&amp;gt; : lowest priority&lt;br /&gt;
::*&amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt; : below normal&lt;br /&gt;
::*&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; : normal priority&lt;br /&gt;
::*&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; : Above normal&lt;br /&gt;
::*&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; : Highest priority&lt;br /&gt;
::*&amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;: Critical priority&lt;br /&gt;
::*&amp;lt;code&amp;gt;31&amp;lt;/code&amp;gt;: Real-time priority&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Computer Name&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;User Name&amp;quot;&amp;lt;/code&amp;gt;: Windows login name&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;User Identity&amp;quot;&amp;lt;/code&amp;gt;: User name in ACP, or Windows login name in DTA.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Windows Version&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Windows SP&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Windows Build&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Abort Event Object&amp;quot;&amp;lt;/code&amp;gt; { ADE only }.  Name of global Event object for ADE project that can be used to send ADE a break signal to abort the current computation.&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;ENV:''«name»''&amp;quot;&amp;lt;/code&amp;gt;: Retrieves the value for the environment variable «name»&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Environment Variables&amp;quot;&amp;lt;/code&amp;gt;: List of all Environment variables&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Command Line&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Analytica Path&amp;quot;&amp;lt;/code&amp;gt;: Full file path to the ''Analytica.exe, Ade.exe'', or ''Ade.dll'' file being run.&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Working Set Size&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Working Set Max&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Working Set Min&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Working Set Flags&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt; &amp;quot;Working Set Peak&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Private Bytes&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Total RAM&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Free RAM&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Total Virtual&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Max Address Space&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Memory Load&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Total Free Memory&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Page Fault Count&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Avail Virtual&amp;quot;&amp;lt;/code&amp;gt; &lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Processor #&amp;quot;&amp;lt;/code&amp;gt;: On a multi-core computer, the processor currently running the current evaluation.  This changes with time.&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Affinity Mask&amp;quot;&amp;lt;/code&amp;gt;: A list of which processors the operating system will allow Analytica's evaluation to run on.&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Num Processors&amp;quot;&amp;lt;/code&amp;gt;: The number of processors the Analytica process is allowed to run on. &lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Num Sys Processors&amp;quot;&amp;lt;/code&amp;gt;: The total number of processors on this computer in the current processor group. Always &amp;lt;=64.{{Release|6.0||&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Num cores&amp;quot;&amp;lt;/code&amp;gt;: The total number of processors on this computer in all [https://docs.microsoft.com/en-us/windows/win32/procthread/processor-groups processor groups]. (Typically the same as &amp;lt;code&amp;gt;&amp;quot;Num Sys Processors&amp;quot;&amp;lt;/code&amp;gt; on computers with 64 cores or less, but can be greater than 64 on very high-end servers).}}&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;User Objects&amp;quot;&amp;lt;/code&amp;gt;: Number of objects in use (variable nodes, local indexes, etc) by a model&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Total Objects&amp;quot;&amp;lt;/code&amp;gt;: Number of objects in use including both user objects and built-in system objects.&lt;br /&gt;
: &amp;lt;code&amp;gt;&amp;quot;Free Objects&amp;quot;&amp;lt;/code&amp;gt;: Number of free &amp;quot;slots&amp;quot; still available for additional objects.{{Release|1=7.1|2=|3=&lt;br /&gt;
: &amp;lt;code&amp;gt;'UI Language'&amp;lt;/code&amp;gt;: Returns the language used for the Analytica user interface, &amp;quot;en&amp;quot;=English, &amp;quot;es&amp;quot;=Spanish, etc. }}{{Release|6.5||&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Application Rect&amp;quot;&amp;lt;/code&amp;gt;: Returns width, height, top, left, as 4 return values, describing the screen coordinates of the desktop Analytica application window. Returns Null in ADE. &lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Desk Rect&amp;quot;&amp;lt;/code&amp;gt;: Returns width, height, x,y, as 4 return values, describing the rectangle within the desktop application where MDI windows can be. This rectangle starts below the toolbar, and does not include application boundaries.}}{{Release|1=7.0|2=|3=&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Python Environments&amp;quot;&amp;lt;/code&amp;gt;: returns a list of all discovered Python/conda environment paths&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Python Installations&amp;quot;&amp;lt;/code&amp;gt;: returns just the base Python installations&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Screenshot&amp;quot;&amp;lt;/code&amp;gt;: Returns an image of the Analytica desktop application window (at the time the function call is evaluated).}}{{Release|1=7.1|2=|3=&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Current Monitor Rect&amp;quot;&amp;lt;/code&amp;gt;: Returns width, height, x, y, as 4 return values, describing the screen coordinates of the monitor that the Analytica application window is currently on. Returns Null in ADE.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Current Monitor Work Rect&amp;quot;&amp;lt;/code&amp;gt;: Returns width, height, x, y, as 4 return values, describing the work area (excluding taskbar) of the monitor that the Analytica application window is currently on. Returns Null in ADE.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Number of Monitors&amp;quot;&amp;lt;/code&amp;gt;: The number of monitors connected to the system.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Monitor ''N'' Rect&amp;quot;&amp;lt;/code&amp;gt;: Returns width, height, x, y, as 4 return values, describing the screen coordinates of the ''N''th monitor (1-based). Replace ''N'' with any integer from 1 to the value of &amp;lt;code&amp;gt;&amp;quot;Number of Monitors&amp;quot;&amp;lt;/code&amp;gt;. For example, &amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Monitor 2 Rect&amp;quot;)&amp;lt;/code&amp;gt; returns the rectangle of the 2nd monitor.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;quot;Monitor ''N'' Work Rect&amp;quot;&amp;lt;/code&amp;gt;: Like &amp;lt;code&amp;gt;&amp;quot;Monitor ''N'' Rect&amp;quot;&amp;lt;/code&amp;gt; but returns the work area (excluding taskbar) of the ''N''th monitor. For example, &amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Monitor 1 Work Rect&amp;quot;)&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
=== Process ID ===&lt;br /&gt;
Knowing the Process ID makes it possible to differentiate between multiple instances of Analytica or [[ADE]] in the Windows Task Manager.  &lt;br /&gt;
:&amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Process ID&amp;quot;) &amp;amp;rarr; 4117&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Reading the command line ===&lt;br /&gt;
:&amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Command Line&amp;quot;) &amp;amp;rarr; '&amp;quot;C:\Program Files\Lumina\Analytica.exe&amp;quot; &amp;quot;C:\My Models\Costs.ana&amp;quot;'&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Analytica Command Line]] for a list of valid command line parameters recognized by Analytica.&lt;br /&gt;
&lt;br /&gt;
=== Reading Environment Variables ===&lt;br /&gt;
Obtain a list of all environment variables:&lt;br /&gt;
:&amp;lt;code&amp;gt;Index EnvVarName := GetProcessInfo(&amp;quot;Environment Variables&amp;quot;);&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Env:&amp;quot;&amp;amp;EnvVarName)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting PID from ADE (C#) ===&lt;br /&gt;
:&amp;lt;code&amp;gt;CAEngine ade = new CAEngine();&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;CAObject V = ade.CreateObject(&amp;quot;V&amp;quot;, &amp;quot;variable&amp;quot;);&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;V.SetAttribute(&amp;quot;definition&amp;quot;, &amp;quot;GetProcessInfo(\&amp;quot;Process ID\&amp;quot;)&amp;quot;);&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;string pInfoResult = V.Result().ToString();&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Aborting an in-progress evaluation in ADE ===&lt;br /&gt;
To abort a computation in [[ADE]], your program must obtain a HANDLE to the ''abort event object''.  In order to obtain this, you need to obtain the name of this object from ADE.  You get this by calling &amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Abort Event Object&amp;quot;)&amp;lt;/code&amp;gt;.  You then use the Windows Platform SDK routine OpenEvent to get the handle to this object.  When you want to abort an in-process computation, you set this event.  Generally your application that uses ADE will need to be multi-threaded, so that one thread calls ADE, the other thread detects the signal to abort the computation (the signal might be a user pressing ''Ctrl+Break'', for example).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:white; border:white; margin-left: 1em;&amp;quot;&amp;gt;&lt;br /&gt;
C++ example:&lt;br /&gt;
&lt;br /&gt;
    /* From first application thread, which uses ADE: */&lt;br /&gt;
    #include &amp;lt;windows.h&amp;gt;&lt;br /&gt;
    #import &amp;quot;ADE.exe&amp;quot;&lt;br /&gt;
    using namespace ADE4;&lt;br /&gt;
    ...&lt;br /&gt;
    GLOBAL HEVENT hAbort;&lt;br /&gt;
    ...&lt;br /&gt;
    void main() &lt;br /&gt;
    {&lt;br /&gt;
        ...&lt;br /&gt;
        CAEngine* pAde = new CAEngine();&lt;br /&gt;
        pAde-&amp;gt;SendCommand(&amp;quot;GetProcessInfo('Abort Event Object')&amp;quot;);&lt;br /&gt;
        _bstr_t abortObjName = pAde-&amp;gt;get_OutputBuffer();&lt;br /&gt;
        hAbort = OpenEvent(EVENT_MODIFY_STATE,/*bInherit*/FALSE,abortObjName);&lt;br /&gt;
        ...&lt;br /&gt;
        CreateThread(..., MonitorForBreak,... );&lt;br /&gt;
        CTable* pResult = pAde-&amp;gt;Get(&amp;quot;X&amp;quot;)-&amp;gt;ResultTable();  /* Initiate a very long computation */&lt;br /&gt;
        if (pAde-&amp;gt;get_ErrorCode() == 78) {&lt;br /&gt;
             /* The computation was aborted before completion */&lt;br /&gt;
             ...&lt;br /&gt;
        }&lt;br /&gt;
        ...&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    DWORD WINAPI MonitorForBreak( LPVOID )&lt;br /&gt;
    {&lt;br /&gt;
         /* This routine detects a signal to break the computation.  Maybe it is a user-keypress,&lt;br /&gt;
          * or other UI interaction. */&lt;br /&gt;
         if (DetectUserWantsToAbort()) {&lt;br /&gt;
             SetEvent(hAbort);                   /* Causes the abort */&lt;br /&gt;
         }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Memory Information ===&lt;br /&gt;
The Analytica process that evaluates your model may end up using a lot of memory.  The operating system keeps some of that memory in RAM, and swaps some of it out to virtual memory.  Accessing RAM is fast, while accessing virtual memory is much slower.  Windows makes various tradeoffs with what other programs are running on your computer to decide how much of the Analytica process to keep in RAM.  The amount of RAM to devote to Analytica is called its ''working set''.  When the working set is much smaller that the available RAM, other applications on your computer will respond well (since they can use that RAM), but Analytica may run slowly.  If the working set is close to the amount of available RAM, then Analytica gets to make more use of fast RAM, but other applications, and the Windows UI, may get very slow, since they will then need to switch in and out of memory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Working Set Max&amp;quot;)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Working set Min&amp;quot;)&amp;lt;/code&amp;gt; return the minimum and maximum working set size, in bytes, currently imposed by Windows on the Analytica process.  &amp;lt;code&amp;gt;GetProcessInfo(&amp;quot;Working Set Flags&amp;quot;)&amp;lt;/code&amp;gt; returns an integer containing flags, indicating whether Windows is allowed to alter these limits as the process uses more or less memory.  The flags are the following numbers added together:&lt;br /&gt;
* &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; = Analytica is guaranteed at least the minimum working set.&lt;br /&gt;
* &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; = Windows may reduce Analytica's working set below the minimum value when memory demands are high&lt;br /&gt;
* &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; = Windows will not allocate more than the indicated working set max.&lt;br /&gt;
* &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; = Windows may give Analytica more than the &amp;lt;code&amp;gt;Working Set Max&amp;lt;/code&amp;gt; when memory demands from other applications is low.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;&amp;quot;Avail Virtual&amp;quot;&amp;lt;/code&amp;gt; option returns the number that Windows reports as the theoretical maximum amount of memory available to all processes running on the operating system, including both RAM and page file space.  However, the number isn't very meaningful or reliable, as Windows often reports a number that far exceeds the amount of available hard disk space (for example, in Windows x64, a number of 8.8 TeraBytes is reported), and in 32-bit processes on Windows x64, the huge number seems to be wrap at 4GB, resulting in a nonesense (and often very small) number.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=6.5|2=|3=&lt;br /&gt;
== Application window coordinates == &lt;br /&gt;
''new in [[Analytica 6.5]]''&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] (width, height, left, top) := [[GetProcessInfo]]( 'Application Rect');&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This gets the rectangle, in screen coordinates, of the desktop application.  From ADE, or ACP when there is no dual desktop UI running, returns Null.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]](width, height) := [[GetProcessInfo]]('Desk Rect');&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This gets the size of the desk, the rectangle within the application where diagram windows, object window, result windows, the outliner, Assista window, etc. reside. This desk rectangle starts below the toolbar. You can also get the location:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]](width, height, x, y) := [[GetProcessInfo]]('Desk Rect');&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The x,y location coordinate is relative to the application window.&lt;br /&gt;
}}&lt;br /&gt;
==History==&lt;br /&gt;
This function was introduced in [[What's new in Analytica 4.0?|Analytica 4.0]].&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
* [[Working Set Size]]&lt;br /&gt;
* [[Memory usage and management]]&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Evaluate&amp;diff=63970</id>
		<title>Evaluate</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Evaluate&amp;diff=63970"/>
		<updated>2026-06-03T20:55:08Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document new maxSeconds parameter (ER 22222), gated to 7.1&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Evaluation Functions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
Evaluate(t) is a powerful, but rarely needed function. If t is text, it parses it as an Analytica expression and evaluates it. If t is a handle to a variable, it evaluates and returns its value.&lt;br /&gt;
== Evaluate(t) ==&lt;br /&gt;
&lt;br /&gt;
If parameter «t» is a [[Text values|text value]],  [[Evaluate]](«t») tries to parse «t» as an Analytica [[expression]] (as in the [[definition]] of a Variable), evaluates it, and returns the resulting [[value]]. For example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Evaluate('10 * 10') &amp;amp;rarr; 100&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If parameter «t» is a [[Handle]] to a variable, [[Evaluate]](«t») evaluates the variable and returns its value:&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 100&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](A)) &amp;amp;rarr; 100&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You can also use it to evaluate a function passed as an object or handle:&lt;br /&gt;
:&amp;lt;code&amp;gt;Function Add(a, b)  :=  a+b&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](Add), 2, 10) &amp;amp;rarr; 12&amp;lt;/code&amp;gt;&lt;br /&gt;
This can be useful when you  want to define a function that takes a function as a parameter and applies the function in its body. &lt;br /&gt;
See [[#Using Evaluate on a Function]] below.&lt;br /&gt;
&lt;br /&gt;
== Handling errors ==&lt;br /&gt;
As of [[Analytica 6.6]], when an error occurs during the parsing or evaluation of «t» ''and'' the call to [[Evaluate]] appears within a [[Try]], evaluation transfers to the «catch» expression of the [[Try]] without presenting any error message dialog to the user. But this isn't true when the only surrounding (possibly nested) [[Try]]s have «errorNum» filters that do not match the occurring error.&lt;br /&gt;
&lt;br /&gt;
If error is not caught by a [[Try]], then a parsing error silently returns [[Null]] and an evaluation error appears to the user like any other evaluation error, typically terminating the computation.&lt;br /&gt;
&lt;br /&gt;
In [[Analytica 6.5]] and earlier, parsing errors are not caught by a surrounding [[Try]] -- they return Null as if there were no surrounding [[Try]].&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
== Capturing console output ==&lt;br /&gt;
''New to [[Analytica 7.1]].''&lt;br /&gt;
&lt;br /&gt;
[[Evaluate]] can optionally return a second value containing the text of everything printed to the console while «t» is evaluated, such as the output of any [[ConsolePrint]]() calls. To request it, capture two return values:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] (result, consoleText) {{eq}} [[Evaluate]]('ConsolePrint(2 + 2)') Do consoleText&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here &amp;lt;code&amp;gt;result&amp;lt;/code&amp;gt; is the value of the evaluated expression (here &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;), and &amp;lt;code&amp;gt;consoleText&amp;lt;/code&amp;gt; is the captured console output (here the text &amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; followed by a newline). Capturing the output does not prevent it from also appearing in the typescript window as it normally does.&lt;br /&gt;
&lt;br /&gt;
The second value captures only output produced ''during'' this evaluation. If «t» refers to a variable whose value is already cached, the variable is not recomputed, so it produces no console output and the captured text is empty.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
== Limiting evaluation time ==&lt;br /&gt;
''New to [[Analytica 7.1]].''&lt;br /&gt;
&lt;br /&gt;
The optional «maxSeconds» parameter sets an approximate limit, in seconds, on how long the evaluation of «t» may run. «maxSeconds» may be fractional, so &amp;lt;code&amp;gt;maxSeconds: 0.1&amp;lt;/code&amp;gt; limits evaluation to roughly 100&amp;amp;nbsp;milliseconds. The default of &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; means no time limit.&lt;br /&gt;
&lt;br /&gt;
If the evaluation does not complete within «maxSeconds», it is aborted and [[Evaluate]] throws an error reading ''&amp;quot;Evaluate reached the maximum time limit of N seconds without completing.&amp;quot;'' Because this is an ordinary evaluation error, you can catch it with a surrounding [[Try]]:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Try]]( [[Evaluate]]('Sum(Sqrt(1..100M))', maxSeconds: 0.5), catch: 'Timed out' )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The timing is approximate -- evaluation stops the next time it checks for interruption -- so the limit adds no measurable overhead to normal evaluation. This makes «maxSeconds» well suited to probing how far a long-running evaluation gets within a time budget, rather than to enforcing a precise deadline.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Limitations of Evaluate(t) ==&lt;br /&gt;
&lt;br /&gt;
There are some subtleties and limitations to Evaluate(«t») when «t» is a text value.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=|2=6.5|3=If text «t» contains a  [[syntax]] error, [[Evaluate]](«t») gives no error message, and returns [[Null]].}}&lt;br /&gt;
&lt;br /&gt;
The context inside the  Evaluate parameter is global, not local. So:&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 100&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable B := ([[Local]] A := 0; [[Evaluate]]('A + 1'))&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;B &amp;amp;rarr; 101&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Variable &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; inside &amp;lt;code&amp;gt;Evaluate('A + 1')&amp;lt;/code&amp;gt; refers to the global &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, not the local &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; defined in &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;. More generally:&lt;br /&gt;
&lt;br /&gt;
* [[Evaluate]](t) creates its own context for [[Parsed Expressions|parsing]] «t» (at evaluation time), which is not the context of the expression in which the [[Evaluate]](t) appears  -- e.g., the definition of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; above.&lt;br /&gt;
* So, text «t» cannot refer to [[Local Values|local value]]s, [[index]]es, or [[function parameters]] defined in the context in which the [[Evaluate]](t) function appears.&lt;br /&gt;
* Text «t» may itself define local values and indexes, and refer to them, but these will not be available outside «t».&lt;br /&gt;
* If the text value of «t» refers to a global variable —e.g., &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; in the definition of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; above—these do not appear as Inputs of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;. &lt;br /&gt;
* More generally, Analytica cannot track the dependency of any variable name that appears inside the text. So, for example, any change to &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; will not cause automatic re-evaluation of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;:&lt;br /&gt;
:&amp;lt;code&amp;gt;A := 3&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;B := A + 1&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;C := Evaluate('A + 1')&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;A := 5&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; changes, Analytica will automatically ensure that &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is updated, but it has no way of knowing &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; should also be recomputed.&lt;br /&gt;
&lt;br /&gt;
The parameter «t» may itself be an expression that creates a text value to be evaluated by [[Evaluate]]. This text expression appears in the definition of &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; and is not subject to the above limitations, so, for example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable V :=([[Local]] x:= ’10’; [[Evaluate]](x &amp;amp; x))&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;V &amp;amp;rarr; 1010&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== When to Use ==&lt;br /&gt;
&lt;br /&gt;
The cases in which you should use [[Evaluate]] are rare.  You should be reluctant to use it due to the caveats listed in the previous section. Typical cases when it is useful include:&lt;br /&gt;
* Parsing simple expressions.&lt;br /&gt;
* (advanced) Use in [[Meta-Inference]] algorithms where you are manipulating handles to objects in your model.&lt;br /&gt;
* (rare) Cases where you really do wish to by-pass dependency maintenance.  You want it to compute something the first time the result is requested after the model is first loaded, but not update when parent values are changes.&lt;br /&gt;
&lt;br /&gt;
== Non-text Parameters ==&lt;br /&gt;
&lt;br /&gt;
A non-text value can also be passed to [[Evaluate]], which can be of use in some [[Meta-Inference]] applications.  You need to keep in mind that the parameter to evaluate is evaluated BEFORE the function itself gets it, so evaluating a non-text value is only meaningful when the evaluated parameter is itself something that can still be evaluated.  One instance of this that is often useful is the case of a [[handle]] an object.&lt;br /&gt;
&lt;br /&gt;
For example, suppose &lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 2  + 3&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable TheVar := [[Handle]](A)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the more general case, you might have a [[Meta-Inference]] algorithm that identifies a single variable object through some computation. Having identified the object, &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; now holds a handle to the object.  You then may want to access values or properties of the object pointed to by &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt;, rather than just values or properties of &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; itself.  Evaluate serves this purpose:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;TheVar &amp;amp;rarr; A   { A -- i.e., a handle to the object A }&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](TheVar) &amp;amp;rarr; 5  { evaluates A }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is worth nothing that an alternative method also exists for evaluating a [[handle]].  You can declare a [[LocalAlias]] set to the handle, and then use its identifier as if it were the identifier of the object.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[LocalAlias]] x := TheVar Do x &amp;amp;rarr; 5    { x is an alias for A, so &amp;quot;x&amp;quot; in the body is the value of A }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When accessing attributes of an object in a [[Meta-Inference]] algorithm, where your algorithm has a handle to an object (again, say it is in &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt;), you can access the attribute using e.g.,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Description Of Evaluate(TheVar) &amp;amp;rarr; &amp;quot;Description of A&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Description Of TheVar &amp;amp;rarr; &amp;quot;Description of TheVar&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(the result of using &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; alone is shown for comparison).&lt;br /&gt;
&lt;br /&gt;
== Using Evaluate on a Function ==&lt;br /&gt;
&lt;br /&gt;
Given a [[handle]] to a function object, you can use [[Evaluate]] to call the function.  If the function expects ''N'' parameters, you would provide ''N+1'' parameters to [[Evaluate]] -- the first parameter being the handle to the function, and the remaining parameters being the values passed to the function.  Example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] fn := [[If]] opt = 1 [[Then]] [[Handle]]([[Max]]) [[Else]] [[If]] opt = 2 [[Then]] [[Handle]]([[Min]]) [[Else]] [[Handle]]([[Sum]]);&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, A, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parameters to the function being called are always passed by position, i.e., you cannot use a named-parameter calling syntax as you might if you were calling the function directly.  &lt;br /&gt;
&lt;br /&gt;
If the function being called contains repeated (or variable number of) parameters, and you need to include a parameter that follows the [[repeated parameter]], then you must place brackets around the repeated parameters.  For example, &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt; Function Fu1(x; y: repeated; z: optional) := ...&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;amp;nbsp;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, 1, 2, 3, 4) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;Fu1(1, 2, 3, 4)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;[2, 3, 4]&amp;lt;/code&amp;gt; are values for &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; is omitted''&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, 1, [2, 3], 4) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;Fu1(1, 2, 3, y: 4)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;[2, 3]&amp;lt;/code&amp;gt; are values for &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; is 4''.&lt;br /&gt;
&lt;br /&gt;
However, there is a limitation that the first supplied parameter (i.e., the second parameter to [[Evaluate]]) cannot be placed inside brackets.  Likewise, you cannot pass an literal list by specifying the first parameter as a bracketed list.  This is because the repeated-parameter syntax applies equally to [[Evaluate]].  If you specify the first parameter to [[Evaluate]] in brackets, those become the parameters to the function, i.e.,:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](F), [1, 2, 3, 4]) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;F(1, 2, 3, 4)''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Several common built-in functions, including [[Sum]], [[Max]], and [[Min]], allow a variable number of indexes, so that you can use &amp;lt;code&amp;gt;[[Sum]](A, I, J, K)&amp;lt;/code&amp;gt; to sum over 3 dimensions in a single call.  These functions also have [[optional parameter]]s, such as «ignoreNonNumbers», so that if you need to specify these optional parameters, you will need to place brackets around the index(es), even if only one (or zero) index is specified.  For example, the following examples show how to to specify «ignoreNonNumbers» as true to [[Sum]], when summing over a single index, and when summing over the [[implicit dimension]]:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]]([[Sum]]), A, [I], true)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] x := [3, 2, 'a', 'b', 6] do [[Evaluate]]([[Handle]]([[Sum]]),  x, [], true)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that if you don't need to specify the optional «ignoreNonNumbers» parameter (or any parameters that follow the repeated index parameters), then it is more natural to omit the brackets:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]]([[Sum]]), A, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] x := [3, 2, 5, 3, 6] do [[Evaluate]]([[Handle]]([[Sum]]), x)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Release|6.5||&lt;br /&gt;
== Evaluating in a different namespace context ==&lt;br /&gt;
''New to [[Analytica 6.5]]''&lt;br /&gt;
&lt;br /&gt;
Suppose there are two variables that both have the identifier X, but which live in different [[Namespaces]]. Then&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]( &amp;quot;X+1&amp;quot; )&amp;lt;/code&amp;gt;&lt;br /&gt;
would differ depending on where it appears. By default it resolves the identifier &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; from the namespace of the object containing the expression. In some esoteric situations, you may need to interpret the expression from a different namespace context.  You can do this by first obtaining a handle to the other namespace module, or to any object inside that namespace, and passing that handle to the «nsContext» parameter.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]( &amp;quot;X+1&amp;quot;, nsContext: [[Handle]](&amp;quot;NS2&amp;quot;) )&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:2;-moz-column-count:2;-webkit-column-count:2&amp;quot;&amp;gt;&lt;br /&gt;
* [[EvaluateScript]]&lt;br /&gt;
* [[Proactive Evaluation]]&lt;br /&gt;
* [[Evaluation Modes]]&lt;br /&gt;
* [[Handle]]&lt;br /&gt;
* [[Expression Syntax]]&lt;br /&gt;
* [[Expression Assist]]&lt;br /&gt;
* [[Parsed Expressions]]&lt;br /&gt;
* [[Function calls and parameters]]&lt;br /&gt;
* [[Summary of Programming Constructs]]&lt;br /&gt;
* [[Procedural Programming]]&lt;br /&gt;
* [[Meta-Inference]]{{Release|6.5||&lt;br /&gt;
* [[Namespaces]]}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Error_Messages/49962&amp;diff=63969</id>
		<title>Error Messages/49962</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Error_Messages/49962&amp;diff=63969"/>
		<updated>2026-06-03T20:41:34Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Error message ==&lt;br /&gt;
:[[Evaluate]] reached the maximum time limit of 3 seconds.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
You called &amp;lt;code&amp;gt;[[Evaluate]]( expr, maxSeconds: 3 )&amp;lt;/code&amp;gt;, and the amount of time spent evaluating «expr» exceeded the specified maximum elapsed time.  &lt;br /&gt;
&lt;br /&gt;
In most usage cases, a call to [[Evaluate]] that uses the «maxSeconds» parameter will be inside a [[Try]], such as:&lt;br /&gt;
 [[Try]] (&lt;br /&gt;
     [[Evaluate]]( expr, maxSeconds:3 )&lt;br /&gt;
 , errorNum: 49962,   { time out }&lt;br /&gt;
 , catch: &lt;br /&gt;
     Null&lt;br /&gt;
 )&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Error_Messages/49962&amp;diff=63968</id>
		<title>Error Messages/49962</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Error_Messages/49962&amp;diff=63968"/>
		<updated>2026-06-03T20:41:00Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Created page with &amp;quot;== Error message == :Evaluate reached the maximum time limit of 3 seconds.  == Description == You called &amp;lt;code&amp;gt;Evaluate( expr, maxSeconds: 3 )&amp;lt;/code&amp;gt;, and the amount o...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Error message ==&lt;br /&gt;
:[[Evaluate]] reached the maximum time limit of 3 seconds.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
You called &amp;lt;code&amp;gt;[[Evaluate]]( expr, maxSeconds: 3 )&amp;lt;/code&amp;gt;, and the amount of time spent evaluating «expr» exceeded the specified maximum elapsed time.  &lt;br /&gt;
&lt;br /&gt;
In most usage cases, a call to [[Evaluate]] that uses the «maxSeconds» parameter will be inside a [[Try]], such as:&lt;br /&gt;
 [[Try]] (&lt;br /&gt;
     [[Evaluate]]( expr, maxSeconds:3 )&lt;br /&gt;
 , errorNum: 49962,&lt;br /&gt;
 , catch: &lt;br /&gt;
     Null&lt;br /&gt;
 )&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63966</id>
		<title>What's new in Analytica 7.1?</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=What%27s_new_in_Analytica_7.1%3F&amp;diff=63966"/>
		<updated>2026-06-01T21:28:06Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: /* Built-in functions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Analytica 7.1 is currently under development, and will be the next future release of Analytica. The current official release is [[Analytica 7.0]]. This page is under construction, and will list enhancements that are new to Analytica or ADE 7.1.&lt;br /&gt;
&lt;br /&gt;
== Window appearance ==&lt;br /&gt;
The appearance of the chrome around child MDI windows (aka the &amp;quot;non-client area&amp;quot;) has been changed to more closely match the Windows 11 style of windows -- i.e., thin (1 pixel) borders, rounded corners at the top, white title bar, very plain (text-like) button images in the toolbar.&lt;br /&gt;
&lt;br /&gt;
== Assista ==&lt;br /&gt;
[[Assista]] is Analytica's A.I. assistant. She is greatly improved in this release.&lt;br /&gt;
* Her UI is now a top-level window that resides at the same level as Analytica's main application window.&lt;br /&gt;
** You can move her chat window to a non-overlapping location or even a different monitor (to maximize screen real estate used by your Analytica window).&lt;br /&gt;
** Selected objects remain visually selected in the main window when you type into Assista.&lt;br /&gt;
* Her chat has a different look-and-feel.&lt;br /&gt;
* Her chat window is faster and more responsive&lt;br /&gt;
* You can drag-highlight any text in her chat and copy to paste elsewhere.&lt;br /&gt;
* The UI has improved formatting capabilities for displaying Assista's response.&lt;br /&gt;
* Her &amp;quot;thoughts&amp;quot; display as she is processing your prompt, making it clear she is working and even giving you a peek into how she is solving it.&lt;br /&gt;
* She has a new processing pipeline on the backend, enabling her to respond faster but also work longer on harder tasks. &lt;br /&gt;
* She has an extended set of competencies (skills). &lt;br /&gt;
* You can create and expose [[Assista_-_Analytica_AI_Assistant/Custom_user_skills_for_Assista|your own custom skills]] to expand her capabilities, or ask her to do it for you.&lt;br /&gt;
* You can drag-and-drop a document (&amp;lt;code&amp;gt;*.txt, *.pdf, *.md, *.docx&amp;lt;/code&amp;gt;) or URLs into the chat which Assista can &amp;quot;ingest&amp;quot; during your conversation. Have her extract data from the doc, adding tables to your model. Or even to implement a model described by the paper.&lt;br /&gt;
* Assista can &amp;quot;see&amp;quot; images in your model -- pictures in nodes, images in table cells, and diagram or graph screenshots.&lt;br /&gt;
* She is language-aware. If you are using Analytica is Spanish, she'll provide UI instructions that refer to the Spanish-language UI elements.&lt;br /&gt;
* She is aware of her reasoning in previous conversation turns and the actions she took, enabling her to explain her reasoning or build on ideas she thought about but might not have included in the final response.&lt;br /&gt;
* She has an improved ability to navigate and find objects within your (large) models.&lt;br /&gt;
&lt;br /&gt;
== Multi-linguality: Spanish UI ==&lt;br /&gt;
Analytica now comes with a Spanish-language UI, in which its menus, dialogs, error messages and built-in function descriptions are all in Spanish. Also its installer runs with a Spanish-language UI when you are in a Spanish-language region.  Spanish is the default when you are in a Spanish-language region. &lt;br /&gt;
&lt;br /&gt;
You can override the default language by launching Analytica as:&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:es&amp;lt;/code&amp;gt;&lt;br /&gt;
*: or&lt;br /&gt;
* &amp;lt;code&amp;gt;Analytica.exe /lang:en&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also set the &amp;lt;code&amp;gt;Language&amp;lt;/code&amp;gt; registry setting in the &amp;lt;code&amp;gt;&amp;quot;HKCU/Software/Lumina Decision Systems/Analytica&amp;quot;&amp;lt;/code&amp;gt; hive to REG_SZ &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for your default if different from your windows region setting.&lt;br /&gt;
&lt;br /&gt;
Some of you may ask &amp;quot;what about my language?&amp;quot;. Stay tuned (and let us know there is a demand for your language). Once our AI translation pipeline is solid, it shouldn't be too hard for us to add more.&lt;br /&gt;
&lt;br /&gt;
== CSV files ==&lt;br /&gt;
There are now a few additional ways to open CSV files in Analytica:&lt;br /&gt;
* On the command line: &amp;lt;code&amp;gt;Analytica.exe MyData.csv&amp;lt;/code&amp;gt;&lt;br /&gt;
* Drag and drop a *.csv file onto the diagram (which behaves the same as using &amp;lt;code&amp;gt;File / Import...&amp;lt;/code&amp;gt; on the *.csv file). &lt;br /&gt;
&lt;br /&gt;
== Spreadsheets ==&lt;br /&gt;
* &amp;lt;code&amp;gt;[[SpreadsheetOpen]](&amp;quot;new&amp;quot;)&amp;lt;/code&amp;gt; now creates a blank spreadsheet in memory. Works with both the Excel and LibXl backends.&lt;br /&gt;
* Prefacing a sheet name with + in the call to [[SpreadsheetSetCell]] or [[SpreadsheetSetRange]] will add a new sheet by that name to the workbook (as it applies the specified change to that new worksheet). Works with either backend.&lt;br /&gt;
* You can also now remove a sheet from a workbook using: &amp;lt;code&amp;gt;[[SpreadsheetSetCell]](wb, &amp;quot;-OldSheet&amp;quot;, col, row, Null)&amp;lt;/code&amp;gt;. The «col» and «row» parameters are required but ignored in this case.&lt;br /&gt;
&lt;br /&gt;
== Misc. User Interface ==&lt;br /&gt;
* The Node Icon editor (on the Diagram menu) is more featureful and can be used to edit arbitrary node images, with support for color and transparency.&lt;br /&gt;
* Added keyboard shortcuts for '''Set Node Style...''' and '''Set Diagram Style...'''&lt;br /&gt;
&lt;br /&gt;
== Built-in functions ==&lt;br /&gt;
* New options for [[GetProcessInfo]]: &amp;lt;code&amp;gt;&amp;quot;Number of monitors&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Current monitor work rect&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;Monitor «N» Rect&amp;quot;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;quot;Monitor «N» work rect&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* New optional parameter, «throwParsingErrors», to [[Evaluate]].&lt;br /&gt;
* [[ReadFromURL]] is a bit smarter about returning binary content (like &amp;lt;code&amp;gt;*.zip&amp;lt;/code&amp;gt; files) as a [[In-memory binary data terms|Binary Data Term]].&lt;br /&gt;
* [[MakeJSON]] will automatically encode an image in base64 JSON, and [[ParseJSON]] will automatically decode a base64 representation into an image.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[GetProcessInfo]](&amp;quot;UI Language&amp;quot;)&amp;lt;/code&amp;gt; returns the UI language, either &amp;lt;code&amp;gt;&amp;quot;en&amp;quot;&amp;lt;/code&amp;gt; (for English) or &amp;lt;code&amp;gt;&amp;quot;es&amp;quot;&amp;lt;/code&amp;gt; for Spanish.&lt;br /&gt;
* &amp;lt;code&amp;gt;[[QualifiedName]]( obj, nsContext )&amp;lt;/code&amp;gt;: Returns the qualified identifier (as text) that uniquely identifies «obj» from the context of «nsContext». &lt;br /&gt;
* &amp;lt;code&amp;gt;[[Namespace]] of X&amp;lt;/code&amp;gt;: A new virtual attribute that returns the namespace of «X».&lt;br /&gt;
* [[Evaluate]] has a second return value that captures output to the typescript window (including stuff written by [[ConsolePrint]]) during the evaluation.&lt;br /&gt;
&lt;br /&gt;
== System variables ==&lt;br /&gt;
* SysVar [[Graph_ColorSequence]]: Replaces [[Graph_ColorSeq]] which is now deprecated. The new sysvar contains a list of color interer with one integer (of the form &amp;lt;code&amp;gt;0x00rrggbb&amp;lt;/code&amp;gt;) per color (whereas the deprecated used triples of numbers per color).&lt;br /&gt;
&lt;br /&gt;
== Engine ==&lt;br /&gt;
* After loading a large model, it parses expressions in parallel, using multiple threads/cores to parse different variables. On some computers on some models, this can dramatically speed up model load time.&lt;br /&gt;
* Color attributes use color integers for consistently (rather than the legacy number triples for R,G,B).&lt;br /&gt;
* You can use a localized namespace import (for a single expression or single lexical block) with the syntax&lt;br /&gt;
*:&amp;lt;code&amp;gt;[[Using..Do|Using]] NS;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Model loading ==&lt;br /&gt;
When opening a model file, the &amp;quot;checking&amp;quot; stage (when attributes are parsed) parses different expressions on different threads, resulting in substantially faster model load times for very large models.&lt;br /&gt;
&lt;br /&gt;
Note: In the event that this creates a problem with your specific model (maybe due to an as-yet-undiscovered multithreading bug), you can disable it for your model as follows:&lt;br /&gt;
# Temporarily turn off multithreading (Skip this step if you are able to load your model)&lt;br /&gt;
## New model&lt;br /&gt;
## &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
## Set to 1  (and remember the previous value)&lt;br /&gt;
# Open your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Disable Multithreaded Evaluations&amp;lt;/b&amp;gt;&lt;br /&gt;
# Press the &amp;lt;code&amp;gt;Edit Table&amp;lt;/code&amp;gt; button.&lt;br /&gt;
# Check the checkbox for &amp;lt;code&amp;gt;Parsing&amp;lt;/code&amp;gt;&lt;br /&gt;
# Save your model&lt;br /&gt;
# &amp;lt;b&amp;gt;Definition menu / System variables / Settings / Maximum evaluation threads&amp;lt;/b&amp;gt;&lt;br /&gt;
#: Restore the original value from Step 1&lt;br /&gt;
&lt;br /&gt;
== MCP server ==&lt;br /&gt;
* Added an ability to install multiple ADE-based Mcp servers that run different ADE releases. For example, you can install two MCP servers into Claude Code:&lt;br /&gt;
* ade-server: Runs ADE 7.1&lt;br /&gt;
* ade-server-70: Runs ADE 7.0&lt;br /&gt;
The information in the &amp;lt;code&amp;gt;«ADE install folder»\Examples\Mcp_server\README.txt&amp;lt;/code&amp;gt; file explain how (with enough info for Claude code to configure this for you).  &lt;br /&gt;
&lt;br /&gt;
With both installed, Claude Code (or other MCP-enabled AI agents) can compare results for the same model across different releases, etc.&lt;br /&gt;
&lt;br /&gt;
Side note: The Mcp server was added to ADE 7.0.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
This release has undergone massive internal restructuring and refactorization. Ideally (i.e., in the absence of bugs) these changes won't change functionality, but may alter some aspects of behavior, hopefully for the better.&lt;br /&gt;
* Internal data structures use for multi-dimensional arrays has been changed. Possible impacts:&lt;br /&gt;
** Likely to remove the sensitivity to the &amp;quot;canonical order&amp;quot; of indexes on evaluation speed.&lt;br /&gt;
** May change relative evaluation speeds of various functions and operations.&lt;br /&gt;
* Added system modules/namespaces: &amp;lt;code&amp;gt;SysLib_Internal&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SysLib_Experimental&amp;lt;/code&amp;gt;. Intended for Analytica-internal use.&lt;br /&gt;
*[[:Category:Cell format functions|Cell formatting functions]] (like [[CellSpan]], [[CellFill]], etc.) are now [[Struct]]s rather than functions. Does not impact usage, other that making it easier for code to traverse resulting data structures.&lt;br /&gt;
&lt;br /&gt;
== Discontinued... ==&lt;br /&gt;
* Plug-in functions. (An old hook that allows you to extend Analytica with compiled functions and UI elements written it C++. We are almost certain no one is using these hooks any more.)&lt;br /&gt;
* The sysvar [[Graph_ColorSeq]] is now deprecated (but works for both reading and setting to preserve backward compatibility). It has been replaced by the system variable [[Graph_ColorSequence]].&lt;br /&gt;
* The built-in (but undocumented, unsupported) &amp;lt;code&amp;gt;ifpos&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;if0&amp;lt;/code&amp;gt; functions were removed.&lt;br /&gt;
* The legacy (deprecated) syntax &amp;lt;code&amp;gt;Using temp:=... Do&amp;lt;/code&amp;gt; for declaring locals is no longer supported. Legacy models will have such definitions automatically rewritten to use [[Local..Do]] when you load them. [[Using..Do]] now has a different meaning, which is to provide a temporary namespace import.&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
	<entry>
		<id>https://docs.analytica.com/index.php?title=Evaluate&amp;diff=63965</id>
		<title>Evaluate</title>
		<link rel="alternate" type="text/html" href="https://docs.analytica.com/index.php?title=Evaluate&amp;diff=63965"/>
		<updated>2026-06-01T21:22:25Z</updated>

		<summary type="html">&lt;p&gt;Lchrisman: Document Evaluate's optional second return value that captures console output (Release 7.1+)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:Evaluation Functions]]&lt;br /&gt;
{{ReleaseBar}}&lt;br /&gt;
&lt;br /&gt;
Evaluate(t) is a powerful, but rarely needed function. If t is text, it parses it as an Analytica expression and evaluates it. If t is a handle to a variable, it evaluates and returns its value.&lt;br /&gt;
== Evaluate(t) ==&lt;br /&gt;
&lt;br /&gt;
If parameter «t» is a [[Text values|text value]],  [[Evaluate]](«t») tries to parse «t» as an Analytica [[expression]] (as in the [[definition]] of a Variable), evaluates it, and returns the resulting [[value]]. For example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Evaluate('10 * 10') &amp;amp;rarr; 100&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If parameter «t» is a [[Handle]] to a variable, [[Evaluate]](«t») evaluates the variable and returns its value:&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 100&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](A)) &amp;amp;rarr; 100&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
You can also use it to evaluate a function passed as an object or handle:&lt;br /&gt;
:&amp;lt;code&amp;gt;Function Add(a, b)  :=  a+b&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](Add), 2, 10) &amp;amp;rarr; 12&amp;lt;/code&amp;gt;&lt;br /&gt;
This can be useful when you  want to define a function that takes a function as a parameter and applies the function in its body. &lt;br /&gt;
See [[#Using Evaluate on a Function]] below.&lt;br /&gt;
&lt;br /&gt;
== Handling errors ==&lt;br /&gt;
As of [[Analytica 6.6]], when an error occurs during the parsing or evaluation of «t» ''and'' the call to [[Evaluate]] appears within a [[Try]], evaluation transfers to the «catch» expression of the [[Try]] without presenting any error message dialog to the user. But this isn't true when the only surrounding (possibly nested) [[Try]]s have «errorNum» filters that do not match the occurring error.&lt;br /&gt;
&lt;br /&gt;
If error is not caught by a [[Try]], then a parsing error silently returns [[Null]] and an evaluation error appears to the user like any other evaluation error, typically terminating the computation.&lt;br /&gt;
&lt;br /&gt;
In [[Analytica 6.5]] and earlier, parsing errors are not caught by a surrounding [[Try]] -- they return Null as if there were no surrounding [[Try]].&lt;br /&gt;
&lt;br /&gt;
{{Release|1=7.1|2=|3=&lt;br /&gt;
== Capturing console output ==&lt;br /&gt;
''New to [[Analytica 7.1]].''&lt;br /&gt;
&lt;br /&gt;
[[Evaluate]] can optionally return a second value containing the text of everything printed to the console while «t» is evaluated, such as the output of any [[ConsolePrint]]() calls. To request it, capture two return values:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] (result, consoleText) {{eq}} [[Evaluate]]('ConsolePrint(2 + 2)') Do consoleText&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here &amp;lt;code&amp;gt;result&amp;lt;/code&amp;gt; is the value of the evaluated expression (here &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;), and &amp;lt;code&amp;gt;consoleText&amp;lt;/code&amp;gt; is the captured console output (here the text &amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; followed by a newline). Capturing the output does not prevent it from also appearing in the typescript window as it normally does.&lt;br /&gt;
&lt;br /&gt;
The second value captures only output produced ''during'' this evaluation. If «t» refers to a variable whose value is already cached, the variable is not recomputed, so it produces no console output and the captured text is empty.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Limitations of Evaluate(t) ==&lt;br /&gt;
&lt;br /&gt;
There are some subtleties and limitations to Evaluate(«t») when «t» is a text value.&lt;br /&gt;
&lt;br /&gt;
{{Release|1=|2=6.5|3=If text «t» contains a  [[syntax]] error, [[Evaluate]](«t») gives no error message, and returns [[Null]].}}&lt;br /&gt;
&lt;br /&gt;
The context inside the  Evaluate parameter is global, not local. So:&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 100&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable B := ([[Local]] A := 0; [[Evaluate]]('A + 1'))&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;B &amp;amp;rarr; 101&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Variable &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; inside &amp;lt;code&amp;gt;Evaluate('A + 1')&amp;lt;/code&amp;gt; refers to the global &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;, not the local &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; defined in &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;. More generally:&lt;br /&gt;
&lt;br /&gt;
* [[Evaluate]](t) creates its own context for [[Parsed Expressions|parsing]] «t» (at evaluation time), which is not the context of the expression in which the [[Evaluate]](t) appears  -- e.g., the definition of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; above.&lt;br /&gt;
* So, text «t» cannot refer to [[Local Values|local value]]s, [[index]]es, or [[function parameters]] defined in the context in which the [[Evaluate]](t) function appears.&lt;br /&gt;
* Text «t» may itself define local values and indexes, and refer to them, but these will not be available outside «t».&lt;br /&gt;
* If the text value of «t» refers to a global variable —e.g., &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; in the definition of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; above—these do not appear as Inputs of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;. &lt;br /&gt;
* More generally, Analytica cannot track the dependency of any variable name that appears inside the text. So, for example, any change to &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; will not cause automatic re-evaluation of &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;:&lt;br /&gt;
:&amp;lt;code&amp;gt;A := 3&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;B := A + 1&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;C := Evaluate('A + 1')&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;A := 5&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; changes, Analytica will automatically ensure that &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is updated, but it has no way of knowing &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; should also be recomputed.&lt;br /&gt;
&lt;br /&gt;
The parameter «t» may itself be an expression that creates a text value to be evaluated by [[Evaluate]]. This text expression appears in the definition of &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt; and is not subject to the above limitations, so, for example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable V :=([[Local]] x:= ’10’; [[Evaluate]](x &amp;amp; x))&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;V &amp;amp;rarr; 1010&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== When to Use ==&lt;br /&gt;
&lt;br /&gt;
The cases in which you should use [[Evaluate]] are rare.  You should be reluctant to use it due to the caveats listed in the previous section. Typical cases when it is useful include:&lt;br /&gt;
* Parsing simple expressions.&lt;br /&gt;
* (advanced) Use in [[Meta-Inference]] algorithms where you are manipulating handles to objects in your model.&lt;br /&gt;
* (rare) Cases where you really do wish to by-pass dependency maintenance.  You want it to compute something the first time the result is requested after the model is first loaded, but not update when parent values are changes.&lt;br /&gt;
&lt;br /&gt;
== Non-text Parameters ==&lt;br /&gt;
&lt;br /&gt;
A non-text value can also be passed to [[Evaluate]], which can be of use in some [[Meta-Inference]] applications.  You need to keep in mind that the parameter to evaluate is evaluated BEFORE the function itself gets it, so evaluating a non-text value is only meaningful when the evaluated parameter is itself something that can still be evaluated.  One instance of this that is often useful is the case of a [[handle]] an object.&lt;br /&gt;
&lt;br /&gt;
For example, suppose &lt;br /&gt;
:&amp;lt;code&amp;gt;Variable A := 2  + 3&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Variable TheVar := [[Handle]](A)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the more general case, you might have a [[Meta-Inference]] algorithm that identifies a single variable object through some computation. Having identified the object, &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; now holds a handle to the object.  You then may want to access values or properties of the object pointed to by &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt;, rather than just values or properties of &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; itself.  Evaluate serves this purpose:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;TheVar &amp;amp;rarr; A   { A -- i.e., a handle to the object A }&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](TheVar) &amp;amp;rarr; 5  { evaluates A }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is worth nothing that an alternative method also exists for evaluating a [[handle]].  You can declare a [[LocalAlias]] set to the handle, and then use its identifier as if it were the identifier of the object.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[LocalAlias]] x := TheVar Do x &amp;amp;rarr; 5    { x is an alias for A, so &amp;quot;x&amp;quot; in the body is the value of A }&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When accessing attributes of an object in a [[Meta-Inference]] algorithm, where your algorithm has a handle to an object (again, say it is in &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt;), you can access the attribute using e.g.,&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;Description Of Evaluate(TheVar) &amp;amp;rarr; &amp;quot;Description of A&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;Description Of TheVar &amp;amp;rarr; &amp;quot;Description of TheVar&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(the result of using &amp;lt;code&amp;gt;TheVar&amp;lt;/code&amp;gt; alone is shown for comparison).&lt;br /&gt;
&lt;br /&gt;
== Using Evaluate on a Function ==&lt;br /&gt;
&lt;br /&gt;
Given a [[handle]] to a function object, you can use [[Evaluate]] to call the function.  If the function expects ''N'' parameters, you would provide ''N+1'' parameters to [[Evaluate]] -- the first parameter being the handle to the function, and the remaining parameters being the values passed to the function.  Example:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] fn := [[If]] opt = 1 [[Then]] [[Handle]]([[Max]]) [[Else]] [[If]] opt = 2 [[Then]] [[Handle]]([[Min]]) [[Else]] [[Handle]]([[Sum]]);&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, A, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Parameters to the function being called are always passed by position, i.e., you cannot use a named-parameter calling syntax as you might if you were calling the function directly.  &lt;br /&gt;
&lt;br /&gt;
If the function being called contains repeated (or variable number of) parameters, and you need to include a parameter that follows the [[repeated parameter]], then you must place brackets around the repeated parameters.  For example, &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt; Function Fu1(x; y: repeated; z: optional) := ...&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;amp;nbsp;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, 1, 2, 3, 4) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;Fu1(1, 2, 3, 4)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;[2, 3, 4]&amp;lt;/code&amp;gt; are values for &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; is omitted''&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]](fn, 1, [2, 3], 4) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;Fu1(1, 2, 3, y: 4)&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;[2, 3]&amp;lt;/code&amp;gt; are values for &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; is 4''.&lt;br /&gt;
&lt;br /&gt;
However, there is a limitation that the first supplied parameter (i.e., the second parameter to [[Evaluate]]) cannot be placed inside brackets.  Likewise, you cannot pass an literal list by specifying the first parameter as a bracketed list.  This is because the repeated-parameter syntax applies equally to [[Evaluate]].  If you specify the first parameter to [[Evaluate]] in brackets, those become the parameters to the function, i.e.,:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]](F), [1, 2, 3, 4]) &amp;amp;rarr;&amp;lt;/code&amp;gt; &lt;br /&gt;
::''Equivalent to &amp;lt;code&amp;gt;F(1, 2, 3, 4)''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Several common built-in functions, including [[Sum]], [[Max]], and [[Min]], allow a variable number of indexes, so that you can use &amp;lt;code&amp;gt;[[Sum]](A, I, J, K)&amp;lt;/code&amp;gt; to sum over 3 dimensions in a single call.  These functions also have [[optional parameter]]s, such as «ignoreNonNumbers», so that if you need to specify these optional parameters, you will need to place brackets around the index(es), even if only one (or zero) index is specified.  For example, the following examples show how to to specify «ignoreNonNumbers» as true to [[Sum]], when summing over a single index, and when summing over the [[implicit dimension]]:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]]([[Sum]]), A, [I], true)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] x := [3, 2, 'a', 'b', 6] do [[Evaluate]]([[Handle]]([[Sum]]),  x, [], true)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that if you don't need to specify the optional «ignoreNonNumbers» parameter (or any parameters that follow the repeated index parameters), then it is more natural to omit the brackets:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]([[Handle]]([[Sum]]), A, I)&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Local]] x := [3, 2, 5, 3, 6] do [[Evaluate]]([[Handle]]([[Sum]]), x)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Release|6.5||&lt;br /&gt;
== Evaluating in a different namespace context ==&lt;br /&gt;
''New to [[Analytica 6.5]]''&lt;br /&gt;
&lt;br /&gt;
Suppose there are two variables that both have the identifier X, but which live in different [[Namespaces]]. Then&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]( &amp;quot;X+1&amp;quot; )&amp;lt;/code&amp;gt;&lt;br /&gt;
would differ depending on where it appears. By default it resolves the identifier &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; from the namespace of the object containing the expression. In some esoteric situations, you may need to interpret the expression from a different namespace context.  You can do this by first obtaining a handle to the other namespace module, or to any object inside that namespace, and passing that handle to the «nsContext» parameter.&lt;br /&gt;
:&amp;lt;code&amp;gt;[[Evaluate]]( &amp;quot;X+1&amp;quot;, nsContext: [[Handle]](&amp;quot;NS2&amp;quot;) )&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&amp;lt;div style=&amp;quot;column-count:2;-moz-column-count:2;-webkit-column-count:2&amp;quot;&amp;gt;&lt;br /&gt;
* [[EvaluateScript]]&lt;br /&gt;
* [[Proactive Evaluation]]&lt;br /&gt;
* [[Evaluation Modes]]&lt;br /&gt;
* [[Handle]]&lt;br /&gt;
* [[Expression Syntax]]&lt;br /&gt;
* [[Expression Assist]]&lt;br /&gt;
* [[Parsed Expressions]]&lt;br /&gt;
* [[Function calls and parameters]]&lt;br /&gt;
* [[Summary of Programming Constructs]]&lt;br /&gt;
* [[Procedural Programming]]&lt;br /&gt;
* [[Meta-Inference]]{{Release|6.5||&lt;br /&gt;
* [[Namespaces]]}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lchrisman</name></author>
	</entry>
</feed>