2
$\begingroup$

I am trying to use the one button to assign to two variables. Here is an example of how I want it to work.

expression:

"Magnitude = ", mstar, ", Distance = ", dstar,

sliders:

"Magnitude:", {{mstar, mSun, "Magnitude"}, mSun, 30},
"Distance:", {{dstar, dSun, "Distance"}, dSun, 600},

buttons:

"or Select Star:", 
{{mstar&&dstar, mAltair&&dAltair, "Star"}, 
 {mAltair&&dAltair -> "Altair", mCanopus&&dCanopus -> "Canopus", 
 mEpisilonIndi&&dEpisilonIndi -> "Episilon Indi"}, 
 ControlType -> Setter}

In this example, it would work fine if it was able to assign both variables when pressing the desired button, however && doesn't work like this. My only solution is to have a button for each variable;

"or Select Star:", 
{{mstar, mAltair, "Subscript[Star, m]"}, 
 {mAltair -> "Altair", mCanopus -> "Canopus", mEpisilonIndi -> "Episilon Indi"}, 
 ControlType -> Setter},

"or Select Star:", 
 {{dstar, mAltair, "Subscript[Star, d]"}, 
  {dAltair -> "Altair", dCanopus -> "Canopus", dEpisilonIndi -> "Episilon Indi"}, 
  ControlType -> Setter}

However, this requires me to press both buttons, where my desired effect is to only have to press one. Is there a way I can achieve this?, I am aware that I can assign a variable two values such as;

Sun = {mSun, dSun}

I don't know the correct expression or even if it's possible. Can I do this and have my expression able to choose which value to use? Like this?

"Magnitude = ", star{value1}, ", Distance = ", star{value2},

"Magnitude:", {{star{value1}, Sun{value1}, "Magnitude"}, Sun{value1}, 30},
"Distance:", {{star{value2}, Sun{Value2}, "Distance"}, Sun{value1}, 600},

"or Select Star:", 
{{star, Sun, "Star"}, 
 {Altair -> "Altair", Canopus -> "Canopus", EpisilonIndi -> "Episilon Indi"}, 
 ControlType -> Setter}

Edit

This is the current coding which displays the first image:

Manipulate[
Column[{Row[{"Apparent magnitude = ", mstar, ", distance = ", dstar, "pc"}], Style[Row[{"Star has Absolute Magnitude of ", mstar - 5 ((Log10[dstar]) - 1)}], Bold, 24]}, Spacings -> {0, 1.5}],
"Choose apparent magnitude:", {{mstar, mSun, "m"}, mSun, 30},
"choose distance:", {{dstar, dSun, "d"}, dSun, 600},
"or select desired star:",
{{mstar, mSun, "m"}, {mAltair -> "Altair", mCanopus -> "Canopus", mEpisilonIndi -> "Episilon Indi", mRigel -> "Rigel", mProximaCentauri -> "Proxima Centauri", mSun -> "Sun", mZetaOphiuchi -> "Zeta Ophiuchi"}, ControlType -> Setter},
{{dstar, dSun, "d"}, {dAltair -> "Altair", dCanopus -> "Canopus", dEpisilonIndi -> "Episilon Indi", dRigel -> "Rigel", dProximaCentauri -> "Proxima Centauri", dSun -> "Sun", dZetaOphiuchi -> "Zeta Ophiuchi"}, ControlType -> Setter}]

Image 1

This is an example of how I want it to be displayed by being able to use a single button to assign both variables. The coding in this second image is a little different using Switch functions for the two variables, however a third variable is required for the actual Switch. I believe this would benefit from being able to assign two individual values to one variable, otherwise the sliders still require two individual variables.

Here is the coding of the two variable switches:

Switch[star, Altair, mRigel, Canopus, mCanopus, EpisilonIndi, mEpisilonIndi, Rigel, mRigel, ProximaCentauri, mProximaCentauri, Sun, mSun, ZetaOphiuchi, mZetaOphiuchi]
Switch[star, Altair, dRigel, Canopus, dCanopus, EpisilonIndi, dEpisilonIndi, Rigel, dRigel, ProximaCentauri, dProximaCentauri, Sun, dSun, ZetaOphiuchi, dZetaOphiuchi]

Here is the coding of the buttons:

{{star, Altair, "s"}, {Altair -> "Altair", Canopus -> "Canopus", EpisilonIndi -> "Episilon Indi", Rigel -> "Rigel", ProximaCentauri -> "Proxima Centauri", Sun -> "Sun", ZetaOphiuchi -> "Zeta Ophiuchi"}, ControlType -> Setter}

As there is now a single variable, star, which assigns the other two, mstar and dstar, the sliders require use of the same variable. A Switch cannot be placed where the star variable is as it's an invalid parameter.

"Choose apparent magnitude:", {{star, mSun, "m"}, mSun, 30},
"Choose distance:", {{star, dSun, "d"}, dSun, 600},

Image 2

Hopefully this makes a more sense, I am very new to Mathematica and have only been using it for about a week.

Edit 2

I adjusted the project to substitute the previous buttons with actual Button functions, it works flawlessly. The following image is how the new output is displayed: Image 3

The buttons are now using the following code:

Button["Altair", mstar = mAltair; dstar = dAltair]
$\endgroup$
4
  • 2
    $\begingroup$ Hi, could you provide the actual pieces of working code? I suppose those are parts of variable specification for Manipulate, aren't they? I'm not sure if I understand your problem but can't you just Button["label", v1=2;v2=5;]? $\endgroup$
    – Kuba
    Nov 30, 2013 at 9:18
  • $\begingroup$ @Kuba Thanks for the response, I haven't used the actual Button function before however that seems like the way I should solve it. I will make an edit to my post with a full example. $\endgroup$ Nov 30, 2013 at 11:18
  • $\begingroup$ @Kuba I applied buttons to the project and it worked successfully, they are a little but larger than I expected, I am looking through the different styles and options to see how I can improve the appearance. I will update a second edit with the new output. $\endgroup$ Nov 30, 2013 at 12:47
  • $\begingroup$ That's great. I know you will get what you want. Take a look at ImageSize/Appearance/Backround and other options for Button. $\endgroup$
    – Kuba
    Nov 30, 2013 at 12:58

1 Answer 1

2
$\begingroup$

Easy fix

To my mind, you have only one variable, the star, and the rest are attributes of the star. Below is a simple way to modify your code to make the Setter work how you desire. I don't know how you want the sliders to work, but getting them to work would be a separate question. Since the code is incomplete, I can't test these modifications completely.

Manipulate[
 With[{mstar = star /. mRules, dstar = star /. dRules},
  Column[{Row[{"Apparent magnitude = ", mstar, ", distance = ", dstar,
       "pc"}],
    Style[
     Row[{"Star has Absolute Magnitude of ", 
       mstar - 5 ((Log10[dstar]) - 1)}], Bold, 24]}, 
   Spacings -> {0, 1.5}]
  ],
 "Choose apparent magnitude:",
 {{mstar, mSun, "m"}, mSun, 30},
 "choose distance:",
 {{dstar, dSun, "d"}, dSun, 600},
 "or select desired star:",
 {{star, "Sun", "star"}, {"Altair", "Canopus", "Episilon Indi", 
   "Rigel", "Proxima Centauri", "Sun", "Zeta Ophiuchi"}, 
  ControlType -> Setter},
 {{mRules, 
   Reverse /@ {mAltair -> "Altair", mCanopus -> "Canopus", 
     mEpisilonIndi -> "Episilon Indi", mRigel -> "Rigel", 
     mProximaCentauri -> "Proxima Centauri", mSun -> "Sun", 
     mZetaOphiuchi -> "Zeta Ophiuchi"}}, None},
 {{dRules, 
   Reverse /@ {dAltair -> "Altair", dCanopus -> "Canopus", 
     dEpisilonIndi -> "Episilon Indi", dRigel -> "Rigel", 
     dProximaCentauri -> "Proxima Centauri", dSun -> "Sun", 
     dZetaOphiuchi -> "Zeta Ophiuchi"}}, None}
 ]

Alternatives

There are few ways to encode your data, including using AstronomicalData.

User-defined functions

Aside from using Rules, another way would be to make function definitions like these for each star.

apparentMag[star] = ...
dist[star] = ...

For example

apparentMag["Sun"] = -26.74;
dist["Sun"] = 4.84820582*^-6;
...

Then, omitting the sliders, you would use them like this:

Manipulate[
 Column[{
   Row[{"Apparent magnitude = ", apparentMag[star], ", distance = ", dist[star], "pc"}],
   Style[Row[{"Star has Absolute Magnitude of ", 
      apparentMag[star] - 5 ((Log10[dist[star]]) - 1)}], Bold, 24]}, 
  Spacings -> {0, 1.5}],
 "or select desired star:",
 {{star, "Sun", "star"}, {"Altair", "Canopus", "EpsilonIndi", "Rigel",
    "ProximaCentauri", "Sun", "ZetaOphiuchi"}, ControlType -> Setter}
 ]

AstronomicalData

To use AstronomicalData, there are a couple of things to be aware of. AstronomicalData is fairly large, by which I mean it can take some time to load initially. It is loaded in segments, so whenever the code encounters unloaded data, there is a pause while the data is downloaded. After it is loaded, it persists on the computer for some time (weeks), and accessing it is fast. Second, you have to use its names for stars, which are general the same as the ordinary name with the spaces stripped out.

To handle the loading of the data, I used the Initialization option to access data about each star. As far as I can tell, this causes the data for each star to be loaded only if it is currently missing. I also set SynchronousInitialization to False, which lets the initialization run as long as it needs to.

Aside: The formula for the absolute magnitude was off from the data in AstronomicalData by 1.5. I don't know which is correct, but I assumed AstronomicalData was.

$stars = {"Altair", "Canopus", "EpsilonIndi", "Rigel", 
   "ProximaCentauri", "Sun", "ZetaOphiuchi"};

Manipulate[
 Column[{Row[{"Apparent magnitude = ", 
     AstronomicalData[star, "ApparentMagnitude"], ", distance = ", 
     AstronomicalData[star, "Distance"], "pc"}],
   Style[Row[{"Star has Absolute Magnitude of ", 
      AstronomicalData[star, "AbsoluteMagnitude"], "(", 
      AstronomicalData[star, "ApparentMagnitude"] - 
       5 ((Log10[AstronomicalData[star, "Distance"]/15428500000000000]) - 
          1) + 1.5, ")"}], Bold, 24]}, Spacings -> {0, 1.5}],
 "or select desired star:",
 {{star, "Sun", "star"}, # -> AstronomicalData[#, "Name"] & /@ $stars,
       ControlType -> Setter},
     Initialization :> (AstronomicalData[#, "Name"] & /@ $stars),
 SynchronousInitialization -> False
 ]
$\endgroup$
4
  • $\begingroup$ Thank you, this was very informative. I will be able to apply this method to another similar project which operates using the same method. I ran through the process you used and applied it to this project, it's optimized far better than how I had wrote it. Thanks for a great alternative. $\endgroup$ Nov 30, 2013 at 13:26
  • $\begingroup$ You're welcome. I added some more alternatives. $\endgroup$
    – Michael E2
    Nov 30, 2013 at 14:18
  • $\begingroup$ Just a note if this helps anyone else, where MichaelE2 used Reverse@{dAltair -> "Altair", the parameters should be reversed like this Reverse@{"Altair" -> dAltair, otherwise it displays the text not the value. @MichaelE2 I have been using AstronomicalData through Initialization, this was the very first thing I learned. there does seem to be some discrepancies between the data and other sources but that's theoretical science in a nutshell. The other alternative seems to require less coding, I will be trying this method out also, thanks. $\endgroup$ Dec 1, 2013 at 8:37
  • $\begingroup$ @AshleyJames Thanks. Actually, I meant Map (/@ instead of just @). It reverses each Rule (->) so that it's the way you wanted. The better way is to retype it in the proper order, but I was lazy. :) I suppose I could have evaluated the Reverse /@ {...} in place. I guess I was really lazy. :P $\endgroup$
    – Michael E2
    Dec 1, 2013 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.