Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt at replacing | with * for creating quantities #693

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

rieder
Copy link
Member

@rieder rieder commented Oct 28, 2020

See issue #687. This PR makes it possible to construct quantities using the * operator, which would previously have resulted in a unit.
With this PR, a unit multiplied/divided by another unit will still give a unit, while other multiplications/divisions will result in a quantity. Of course, quantities can still be converted to units with .to_unit().

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020

Using the | operator to create quantities is still possible with this PR by the way - but if merged, we should add a deprecation warning to that method.

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020

I think the impact should be minimal with this PR - only scripts that construct new units will need modification, and I don't recall ever writing such a script myself.

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020

Clearly not yet finished :).

@ipelupessy
Copy link
Member

how does it do with the tests?

@ipelupessy
Copy link
Member

ipelupessy commented Oct 28, 2020

its very hard to review with the zillion formatting changes... [its not a good sign when github refuses to load the diff]

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020

Lots of errors so far, working on fixing them.
One problem is that the order of constructing units/quantities needs to be taken into account.
Not sure what we can do about that except advising that any unit should be constructed first before assigning it to a value, using parentheses or something.

@ipelupessy
Copy link
Member

can you give an example of that?

what happens if you keep the old overload available?

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020

it's still available, but some constructed units are now suddenly quantities.
Leads to errors like this:

In [4]: (constants.Rydberg_constant * constants.h * constants.c)
   ...:
   ...:
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-4-4f3dad978eb6> in <module>
----> 1 (constants.Rydberg_constant * constants.h * constants.c)
      2

~/Code/amuse/src/amuse/units/quantities.py in __mul__(self, other)
    125     def __mul__(self, other):
    126         other = to_quantity(other)
--> 127         return new_quantity_nonone(self.number * other.number, (self.unit * other.unit).to_simple_form())
    128
    129     __rmul__ = __mul__

~/Code/amuse/src/amuse/units/quantities.py in __mul__(self, other)
    125     def __mul__(self, other):
    126         other = to_quantity(other)
--> 127         return new_quantity_nonone(self.number * other.number, (self.unit * other.unit).to_simple_form())
    128
    129     __rmul__ = __mul__

~/Code/amuse/src/amuse/units/quantities.py in new_quantity_nonone(value, unit)
   1215     :returns: new ScalarQuantity or VectorQuantity object
   1216     """
-> 1217     if not unit.base:
   1218         if isinstance(value, __array_like):
   1219             return numpy.asarray(value) * unit.factor

AttributeError: 'ScalarQuantity' object has no attribute 'base'

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020

its very hard to review with the zillion formatting changes... [its not a good sign when github refuses to load the diff]

should be a bit easier now. Main changes are in core.py.

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020

can you give an example of that?

c = 299792458.0 * (m*s**-1) is fine, but c = 299792458.0 * m*s**-1 is not:

In [7]: c = 299792458.0 * m*s**-1

In [8]: c
Out[8]: quantity<299792458.0 s**-1 m>

In [9]: c.unit
Out[9]: unit<m>

In [10]: c.number
Out[10]: quantity<299792458.0 s**-1>

In [11]: c = 299792458.0 * (m*s**-1)

In [12]: c
Out[12]: quantity<299792458.0 m * s**-1>

In [13]: c.unit
Out[13]: unit<m * s**-1>

In [14]: c.number
Out[14]: 299792458.0

@ipelupessy
Copy link
Member

does the ror still work after this?

maybe is also good to take stock of all the implications that this change has (issue?):

  • old simulation scipts
  • documentation
  • book
  • sandbox
  • downstream (dependend packages ie omuse)
  • etc

@rieder
Copy link
Member Author

rieder commented Oct 28, 2020 via email

@ipelupessy
Copy link
Member

ipelupessy commented Oct 29, 2020

quantities has a as_unit and a to_unit - they are slightly different...don't know why.. (i prefer the name to_unit, don't know about implementation yet)

also - there are a bunch of as_units that can be removed and I think in the constants definition we can also remove '* none' units

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

Another issue:
1.0 * unit will return the unit. This should probably return a quantity instead (in line with previous behaviour and other unit systems)

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

Another issue:
1.0 * unit will return the unit. This should probably return a quantity instead (in line with previous behaviour and other unit systems)

units.kg.__mul__(1.0) does return a quantity. Apparently with 1.0 * units.kg this isn't even called.

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

ah, of course that would be __rmul__...

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

This also fails:

In [31]: 2.0 * 2.0 * kg * m**2
Out[31]: quantity<4.0 m**2 kg>

In [32]: 2.0 * 2.0 * kg**2 * m**2
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-32-7f60638bbeb4> in <module>
----> 1 2.0 * 2.0 * kg**2 * m**2

~/Code/amuse/src/amuse/units/quantities.py in __mul__(self, other)
    125     def __mul__(self, other):
    126         other = to_quantity(other)
--> 127         return new_quantity_nonone(self.number * other.number, (self.unit * other.unit).to_simple_form())
    128
    129     __rmul__ = __mul__

~/Code/amuse/src/amuse/units/quantities.py in new_quantity_nonone(value, unit)
   1214     :returns: new ScalarQuantity or VectorQuantity object
   1215     """
-> 1216     if not unit.base:
   1217         if isinstance(value, __array_like):
   1218             return numpy.asarray(value) * unit.factor

AttributeError: 'ScalarQuantity' object has no attribute 'base'

also:

In [33]: (2.0 * 2.0 * kg * m**2).unit
Out[33]: unit<kg>

In [34]: (2.0 * 2.0 * kg * m**2).number
Out[34]: quantity<4.0 m**2>

@ipelupessy
Copy link
Member

hmm, not sure this goes ok....

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

it's really tricky...

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

This is what's happening internally:

In [2]: 1.0 * (kg * m)
mul (kg, m)  # self, other
rmul (kg * m, 1.0)  # self, other
Out[2]: quantity<1.0 kg * m>

In [3]: 1.0 * kg * m
rmul (kg, 1.0)
rmul (m, 1.0)
mul (kg, none)
Out[3]: quantity<1.0 m kg>

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

And

In [4]: 1.0 * kg**2 * m
rmul (kg**2, 1.0)
rmul (m, 1.0)
mul (kg**2, none)
rmul (kg**2, 1)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)```

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

In astropy:

In [9]: 1.0 * u.kg**2 * u.m
rmul kg2 1.0
mul m kg2
Out[9]: <Quantity 1.0 kg2 m>```

src/amuse/units/core.py Outdated Show resolved Hide resolved
return factor_unit(other, self)
return self.new_quantity(other)
if isinstance(other, unit):
return factor_unit(other, self)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is wrong, because factor units are supposed to construct from a number(like) and a unit..you should only get here with other a number..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced it with mul_unit, I think that's correct?

@ipelupessy
Copy link
Member

btw ignore the review, these are just comments

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

comments are useful, I won't ignore them :)

@ipelupessy
Copy link
Member

would it work if 1000*m resolves to a quantity and m*1000 to a unit?

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

Yes, changing the order seems to work:

In [12]: 3.206361533e-53 * C**3*m**3*J**-2
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-12-545b55826c72> in <module>
----> 1 3.206361533e-53 * C**3*m**3*J**-2

~/Code/amuse/src/amuse/units/quantities.py in __mul__(self, other)
    125     def __mul__(self, other):
    126         other = to_quantity(other)
--> 127         return new_quantity_nonone(self.number * other.number, (self.unit * other.unit).to_simple_form())
    128
    129     __rmul__ = __mul__

~/Code/amuse/src/amuse/units/core.py in to_simple_form(self)
    211                     result = result * base
    212             else:
--> 213                 result =  result * (base ** n)
    214
    215         return result

~/Code/amuse/src/amuse/units/quantities.py in __mul__(self, other)
    125     def __mul__(self, other):
    126         other = to_quantity(other)
--> 127         return new_quantity_nonone(self.number * other.number, (self.unit * other.unit).to_simple_form())
    128
    129     __rmul__ = __mul__

~/Code/amuse/src/amuse/units/quantities.py in new_quantity_nonone(value, unit)
   1214     :returns: new ScalarQuantity or VectorQuantity object
   1215     """
-> 1216     if not unit.base:
   1217         if isinstance(value, __array_like):
   1218             return numpy.asarray(value) * unit.factor

AttributeError: 'ScalarQuantity' object has no attribute 'base'

In [13]: C**3*m**3*J**-2 * 3.206361533e-53
Out[13]: quantity<3.206361533e-53 C**3 * m**3 * J**-2>

@ipelupessy
Copy link
Member

did you see the comment on line 87 of core? (rmul)

@ipelupessy
Copy link
Member

also the check for a numerical factor of exactly one should then maybe go to __mul__ or do something with factor_unit, but that is tricky...

@rieder
Copy link
Member Author

rieder commented Oct 29, 2020

did you see the comment on line 87 of core? (rmul)

yes, I think it's fixed now. Error is gone at least.
edit: no, it's not

@ipelupessy
Copy link
Member

ipelupessy commented Jan 7, 2021

can you make a version w/o formatting changes? its very hard to see where it stands now
its not so bad actually, though its a bit annoying to combine formatting with nonformatting changes...in any case have you looked at this further?

@stale
Copy link

stale bot commented Mar 4, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Mar 4, 2022
@ipelupessy
Copy link
Member

keep open

@stale
Copy link

stale bot commented May 4, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 28 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale Issues that have been around for a while without updates label May 4, 2022
@rieder rieder removed the stale Issues that have been around for a while without updates label May 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants